User:Thepigdog/Inheritance

From Knowino
Jump to: navigation, search

Contents

[edit] Naming

A naming system allows us to name language elements,

The naming system allows us define a naming path for language elements. For example,

animal.mammal.dog

Language also provides naming scope, which means that you can reference language elements without referencing the full name. The scope is a region of the program in which a name prefix is defined.

So if I define a namespace,

namespace animal.mammal
{
dog refers to animal.mammal.dog
}

[edit] Variables

A variable is a reference to an object.

[edit] Functions

Functions define mappings between objects (referenced by parameter variables).

A function is identified by its signature. The signature consists of,

Each function has an associated pre-condition which determines if a call is invoked. A call may invoke multiple functions.

[edit] Return Type in the Signature

Note that many languages do not treat the return type as part of the signature. From a structural point of view a return type is similar to a parameter. If we write,

n = Factorial(6)

or

Factorial(n, 6)

the meaning (with a suitable overloading of the Factorial function) would be identical.

There are situations where overloading by return type would be useful.

[edit] Object

Every object has two primary attributes,

Identity means that two objects can be distinguished, and two references refering to the same object will be equal.

Also we can ask what class the object belongs to. Class defines membership of a set.

[edit] Project

A project is a grouping of classes that work together to offer services to the outside world.

[edit] Class

A class is a set of objects. Every Class has attributes,

[edit] Abstraction and Encapsulation

Abstraction and Encapsulation is the hiding of language elements so that they may only be accessed from certain scopes. The language defines the rules which control the accessibility of objects, using keywords such as,

Along with the control of reference object oriented programming uses a different syntax for calling functions that are defined within a classes scope,

    name.Equals("Roger")

is used instead of,

    String.Equals(name, "Roger")

This as purely a syntactical difference, of no fundamental significance. Both these calls should be legal and mean exactly the same thing.

Of course syntactical issues are important. The human brain is better at reading syntax which is varied and gives hints as to the usage. A language like LISP that is all brackets may be fine for the computer but counting brackets and understanding complex expressions may be difficult for the human reader.

[edit] Inheritance

Inheritance defines a set membership relationship between the objects that belong to classes. If class A inherits from class B then an object from class A also belongs to class B.

Class is like a compile time version of set theory. The following table describes the correspondence.

Classification of Symbolic Logic Systems
Classes Sets Maths
A inherits from B A is a subset of B A \subset B
Declaring - class A a = new A() a is a member of A a \in A
A inherits from B and class A a = new A() a is a member of A and B a \in A \and a \in B

[edit] Polymorphism

Polymorphism refers to the conditions under which a function is called. There is logically a pre-condition associated with each function call. The pre-condition includes,

[edit] Overriding Functions

[edit] Virtual

A virtual function is a function that has an extra pre-condition. The pre-condition is that the method signature is not also defined in an inheriting class that the object belongs to.

If a class Square inherits from ShortRectangle and ShortRectangle implements the virtual function Validate.

    Square inherits ShortRectangle
 
    virtual bool ShortRectangle.Validate()
    {
        return Width() < Height();
    }
 
    virtual bool Square.Validate()
    {
        return Width() = Height();
    }
 
    class Square a = new Square();

Logically everything true about the base class should be true about the base class should be true also in the inheriting class. But overriding a virtual function in a child class disables the implementation in the base class. Logically a virtual function has a pre-condition that the function is only applied if not overridden in the implemented class.

A virtual function is a default implementation of a function only. There is no guarantee implemented in the function will be used in a derived class. So anything definite that we want to say about a class should not be in a virtual function.

[edit] Non Virtual

The implementation of non virtual functions in most languages is illogical (e.g. C++). For a non virtual function the implementation may still be overridden in the base class. But now which method we get depends on the type of the variable. This is inconsistent with mathematical logic.

Logic says that any true fact about a base class should also be true in the inheriting class. For virtual functions we were able to get around this with the idea of a pre-condition on the method.

But for non virtual functions a call to the function must call the base class implementation and the child class implementation, in order to be logically consistent.

[edit] Overloading

Overloading is where the same function name may be defined multiple times for the same class. A function can only be defined once for its function signature.

It is possible for multiple functions to be invoked for the same function call. This is occurs when there is a "polymorphic change of type".

My view is that in this case both functions should be called, and the results combined. How the results are combined is described in the Renaming Inheritance section.

The use of overloading may make code very confusing. But overloading also has its uses and is logically equivalent to polymorphism.

[edit] Renaming Inheritance

Inheritance is related to set membership. If A inherits from B this means that A is a subset of B. An object of class A is also in class B.

The functions of class A can access the functions from class B. Also if class A overrides virtual functions the class B can gain access to the functions of class A. This two way relationship implements a relationship between the two classes.

But when a class has a member variable there is only a one relationship. This means that the member variable class functions have no way of calling functions on the base class.

[edit] Bank Vault Example

Suppose a bank has two bank vaults. The alarm should go off in the bank if either vault is opened without authorization.

The Vault class calls the Alarm() method if the vault is opened without authorisation.

class Vault
{
protected:
abstract void Alarm() rename as Alarm%; // Alarm% is the template for the name in the inheriting class.
private:
void Open()
{
if (not Authorised)
{
Alarm();
}
}
}

The Bank class has two vaults called Main and Secondary. It needs to respond to the Alarm raised from either Vault.

class Bank
{
inherit Vault as VaultMain
inherit Vault as VaultSecondary
// In heriting from Vault as VaultMain Bank, inherits the Alarm method which is renamed.
// The rename template Alarm% is used with % substituted with VaultMain to give the inherited name.
void AlarmVaultMain()
{
Logger.Write("Alarm on main vault");
Alarm();
}
// The rename template Alarm% is used with % substituted with VaultSecondary to give the inherited name.
void AlarmVaultSecondary()
{
Logger.Write("Alarm on secondary vault");
Alarm();
}
}

[edit] Details

The "rename as" keywords indicate that the function will be inherited using renaming inheritance.

The template provided after "rename as" is used to construct the name of the function in the inheriting class. If there is a % in the template it is replaced by the inherited name.

In the above example the "rename as" template of the Alarm function is Alarm%. So when Vault is inherited as VaultMain the name of the Alarm function is AlarmVaultMain in the bank class.

If there was no % in the name the new name would be just the template. For example if there was a function,

abstract void GeneralAlarm() rename as GeneralAlarm;

then the Bank class would inherit the one GeneralAlarm method.

The declaration,

inherit Vault as VaultMain

differs from a member variable in that there is no member variable to access. Only the renamed functions provide access the inherited class.

[edit] Shared Signature

If the % is ommitted from the renaming template then if the base class inherits the same class multiple times the same signature may be implemented multiple times. This is called signature sharing. In fact signature sharing may occur without using renaming inheritance.

Logically in this case all the implementations should be inherited. A call to a function should invoke all functions that match the signature.

The logical interpretation is that all these separate implementations should be consistent. They should return the same result given the same inputs.

But it is helpfull to provide another interpretation of this. A combination operator may be provided that combines the results together. For a function that returns a boolean this operator would be "and" by default.

Shared inheritance allows code the traversal of an object structure. For example it allows ever attribute of an object to be visited for purposes such as validation or saving data to a database.

[edit] Alternatives

Here are some alternatives provided in different languages,

The reason renaming inheritance is suggested is that it allows localisation of implementation. Each class can deal locally with functionality required for itself, while communicating with an inheriting class if needed. The results of local calculations can then be automatically combined together to form a global result, through name sharing.

Personal tools
Namespaces
Variants
Actions
Navigation
Community
Toolbox