четверг, 26 февраля 2015 г.

Containers 10. About patterns and mixins

Original in Russian: http://18delphi.blogspot.ru/2013/03/blog-post_29.html

About containers. Table of contents

Now let’s talk about mixins a bit.

The theory can be read here:
https://en.wikipedia.org/wiki/Mixin

Instead, we’ll go in for practice.

Let’s look at the definition:
In object-oriented programming languages, a mixin is a class that contains a combination of methods from other classes. How such a combination is done depends on the language, but it is not by inheritance. If a combination contains all methods of combined classes, it is equivalent tomultiple inheritance.
Mixins encourage code reuse and can be used to avoid the inheritance ambiguity that multiple inheritance can cause (the "diamond problem"), or to work around lack of support for multiple inheritance in a language.
A mixin can also be viewed as an interface with implemented methods. When a class includes a mixin, the class implements the interface and includes, rather than inherits, all the mixin's attributes (fields, properties) and methods. They become part of the class during compilation.
A mixin can defer definition and binding of methods untilruntime, though attributes and instantiation parameters are still defined at compile time. This differs from the most widely used approach (which originated in the programming language Simula) of defining all attributes, methods and initialization at compile time.

Those who code on C++ are lucky, because they have multiple inheritance and the question “how to add mixin to the existing class hierarchy” does not arise. Delphi programmers are not lucky. There is no multiple inheritance. Actually, thank God – mixins are far more highly specialized tool then multiple inheritance.

I will write separately about the particular examples of using the mixins in life. And now let’s consider a purely abstract example illustrating only the technique of embedding the mixin class to the hierarchy of inheritance of designed classes.

In the previous article we had an example:

Let’s redraw the diagram in this way:


We can see that functionality of Stack'а has completely moved to StackPrim.
And two more classes have appeared – TintStackFromPersisten, inherited from TPersistent and StackPrim, and class TIntStackFromComponent, inherited from TComponent and StackPrim.

Multiple inheritance – you’d ask. Logically – yes. At the level of the diagrams arrows.

Let’s see how it all looks on Delphi:
StackPrim.imp.pas:

{$IfNDef StackPrim_imp}
 
{$Define StackPrim_imp}
 ItemsHolder = array of _ItemType_;
 
 _StackPrim_ = {mixin} class(_StackPrim_Parent_)
 private
 // private fields
   f_Items : ItemsHolder;
 public
 // public methods
   procedure Push(const anItem: _ItemType_);
   function Pop: _ItemType_;
 end;//_StackPrim_
 
{$Else StackPrim_imp}
 
// start class _StackPrim_
 
procedure _StackPrim_.Push(const anItem: _ItemType_);
var
 l_L : Integer;
begin
 l_L :=  Length(f_Items);
 SetLength(f_Items, l_L + 1);
 f_Items[l_L] := anItem;
end;//_StackPrim_.Push
 
function _StackPrim_.Pop: _ItemType_;
var
 l_L : Integer;
begin
 l_L :=  Length(f_Items) - 1;
 Result := f_Items[l_L];
 SetLength(f_Items, l_L);
end;//_StackPrim_.Pop
 
{$EndIf StackPrim_imp}

---------------------------------------------
Stack.imp.pas:

{$IfNDef Stack_imp}
 
{$Define Stack_imp}
 _StackPrim_Parent_ = TObject;
 {$Include StackPrim.imp.pas}
 _Stack_ = {mixin} class(_StackPrim_)
 end;//_Stack_
 
{$Else Stack_imp}
 
{$Include StackPrim.imp.pas}
 
{$EndIf Stack_imp}

---------------------------------------------
StringStack.pas:

unit StringStack;
 
interface
 
type
 _ItemType_ = AnsiString;
 {$Include Stack.imp.pas}
 TStringStack = class(_Stack_)
 end;//TStringStack
 
implementation
 
{$Include Stack.imp.pas}
 
end.

---------------------------------------------
IntStack.pas:

unit IntStack;
 
interface
 
type
 _ItemType_ = Integer;
 {$Include Stack.imp.pas}
 TIntStack = class(_Stack_)
 end;//TIntStack
 
implementation
 
{$Include Stack.imp.pas}
 
end

---------------------------------------------
!!! And there are two NEW classes:
---------------------------------------------
IntStackFromPersistent.pas:

unit IntStackFromPersistent;
 
interface
 
uses
  Classes
  ;
 
type
 _ItemType_ = Integer;
 _StackPrim_Parent_ = TPersistent;
 {$Include StackPrim.imp.pas}
 TIntStackFromPersistent = class(_StackPrim_)
 end;//TIntStackFromPersistent
 
implementation
 
{$Include StackPrim.imp.pas}
 
end.

---------------------------------------------
IntStackFromComponent.pas:

unit IntStackFromComponent;
 
interface
 
uses
  Classes
  ;
 
type
 _ItemType_ = Integer;
 _StackPrim_Parent_ = TComponent;
 {$Include StackPrim.imp.pas}
 TIntStackFromComponent = class(_StackPrim_)
 end;//TIntStackFromComponent
 
implementation
 
{$Include StackPrim.imp.pas}
 
end.

---------------------------------------------

As for me, it is fun :-) There is only ONE mixin, but it is added to FOUR different classes and even different places in the hierarchy of the inheritance.

Try it. May be you will like it.

In the next series I will try to tell WHY do I use it.

Комментариев нет:

Отправить комментарий