May 27, 2007
eao197 wrote:
> Disclaimer. Yes, I know that Sensor could mixin Subject, not inherit it. But I think there is probability that in some situation inheritance must be used by some very important reasons.
I think mixins actually are the best way to do this. Here's how they would look with your example (note that there is very little modification of the code):

> template Subject(O, S)
> {
>     private O[] observers_ = [];
>     
>     public void subscribe(O observer)
>     {
>         observers_ ~= observer;
>     }
> 
>     public void publish()
>     {
>         foreach ( o; observers_ )
>             o.notify( this );
>     }
> }
> 
> interface Observer(S)
> {
>     void notify(S subj);
> }
> 
> class Sensor
>   {
>     mixin Subject!(Display, Sensor);
> 
>     private char[] label_;
>     private double value_;
> 
>     this( char[] label, double value )
>       {
>         label_ = label.dup;
>         value_ = value;
>       }
> 
>     char[] label() { return label_; }
>     double value() { return value_; }
>     void value( double v ) { value_ = v; publish; }
>   }
> 
> class Display : Observer!(Sensor)
>   {
>     void notify( Sensor subj )
>       {
>         Stdout( subj.label )( " has value " )( subj.value ).newline;
>       }
>   }

Using the syntax Subject is S automatically requires that any implementors of Subject!(Display, Sensor) inherit from Sensor. So why not simply make Sensor the inheritance root, as the mixin does? I don't see that any information is lost this way.

-- Reiner
May 27, 2007
On Sun, 27 May 2007 05:23:55 +0400, Reiner Pope <some@address.com> wrote:

>>  class Sensor
>>   {
>>     mixin Subject!(Display, Sensor);
>>      private char[] label_;
>>     private double value_;
>>      this( char[] label, double value )
>>       {
>>         label_ = label.dup;
>>         value_ = value;
>>       }
>>      char[] label() { return label_; }
>>     double value() { return value_; }
>>     void value( double v ) { value_ = v; publish; }
>>   }
>>  class Display : Observer!(Sensor)
>>   {
>>     void notify( Sensor subj )
>>       {
>>         Stdout( subj.label )( " has value " )( subj.value ).newline;
>>       }
>>   }
>
> Using the syntax Subject is S automatically requires that any implementors of Subject!(Display, Sensor) inherit from Sensor. So why not simply make Sensor the inheritance root, as the mixin does? I don't see that any information is lost this way.

In that example Sensor doesn't inherit from Subject. The base type for Sensor is Object.
But may be situations in such a class must be inherited from some domain-specific base class.

-- 
Regards,
Yauheni Akhotnikau
May 27, 2007
eao197 wrote:
> On Sun, 27 May 2007 05:23:55 +0400, Reiner Pope <some@address.com> wrote:
> 
>>>  class Sensor
>>>   {
>>>     mixin Subject!(Display, Sensor);
>>>      private char[] label_;
>>>     private double value_;
>>>      this( char[] label, double value )
>>>       {
>>>         label_ = label.dup;
>>>         value_ = value;
>>>       }
>>>      char[] label() { return label_; }
>>>     double value() { return value_; }
>>>     void value( double v ) { value_ = v; publish; }
>>>   }
>>>  class Display : Observer!(Sensor)
>>>   {
>>>     void notify( Sensor subj )
>>>       {
>>>         Stdout( subj.label )( " has value " )( subj.value ).newline;
>>>       }
>>>   }
>>
>> Using the syntax Subject is S automatically requires that any implementors of Subject!(Display, Sensor) inherit from Sensor. So why not simply make Sensor the inheritance root, as the mixin does? I don't see that any information is lost this way.
> 
> In that example Sensor doesn't inherit from Subject. The base type for Sensor is Object.
> But may be situations in such a class must be inherited from some domain-specific base class.

I simply can't see the situation you describe. Suppose we had a situation where you needed multiple classes to inherit from Subject!(Display, Sensor). Well, why would that be? Presumably so you can use them polymorhpically, perhaps something like the following:

void main()
{
    // Let's suppose we could actually have a base type
    // Subject!(Display, Sensor) from which everything
    // was derived. Suppose 'self' is possible.
    alias Subject!(Display, Sensor) SubjectType;
    SubjectType[] allSubjects = getListOfAllSubjects();

    Observer!(Sensor) myGenericObserver = new Display();
    foreach (s; allSubjects)
        s.subscribe(myGenericObserver);
}

For example, perhaps you have lots of things which need specific observers, and you additionally want to log everything using myGenericObserver. In that case, it is beneficial for all the classes to be inherited from Subject!(Display, Sensor).

But the condition 'Subject is S' already requires that 'this' for any descendant of Subject!(Display, Sensor) can be implicitly converted to Sensor. Which means that any class which inherits from Subject!(Display, Sensor) also inherits from Sensor. So you can rewrite my example above as

void main()
{
    // Now we don't need to have a base
    // type Subject!(Display, Sensor). Instead,
    // our base type is simply Sensor (which is
    // implemented with a mixin)
    Sensor[] allSubjects = getListOfAllSubjects();

    Observer!(Sensor) myGenericObserver = new Display();
    foreach (s; allSubjects)
        s.subscribe(myGenericObserver);
}

   -- Reiner
May 27, 2007
On Sun, 27 May 2007 09:26:56 +0400, Reiner Pope <some@address.com> wrote:

>>> Using the syntax Subject is S automatically requires that any implementors of Subject!(Display, Sensor) inherit from Sensor. So why not simply make Sensor the inheritance root, as the mixin does? I don't see that any information is lost this way.
>>  In that example Sensor doesn't inherit from Subject. The base type for Sensor is Object.
>> But may be situations in such a class must be inherited from some domain-specific base class.
>
> I simply can't see the situation you describe. Suppose we had a situation where you needed multiple classes to inherit from Subject!(Display, Sensor).

That is not a desired situation :)
I don't want multiple classes inherited from Subject!(Display, Sensor). I want to have multiple distinct classes inherited from Subject (for example: SubjectObserver!(Notificator, Account) for banking accounting system, SubjectObserver!(Display, Sensor) for data acquisition system, SubjectObserver!(Mailbox, Topic) for message delivery system and so on)). Class Subject in template SubjectObjserver may be inherited from another useful class (Serializabe, Loggable, Dumpable or something else). This means that in the following case:

class Account : SubjectObserver!(Notificator, Account).Subject { ... }
class Topic : SubjectObserver!(Mailbox, Topic).Subject { ... }

classes Account and Topic will be automatically derived from Serializable (Loggable, Dumpable, ...) too.

In case of:

class Account {
  mixin Subject!(Notificator, Account);
  ...
}
class Topic {
  mixin Subject!(Mailbox, Topic);
  ...
}

it is neccessary to derive Account and Topic from Serializable (Loggable, Dumpable, ...) manually.

-- 
Regards,
Yauheni Akhotnikau
May 27, 2007
eao197 wrote:
> That is not a desired situation :)
> I don't want multiple classes inherited from Subject!(Display, Sensor). I want to have multiple distinct classes inherited from Subject (for example: SubjectObserver!(Notificator, Account) for banking accounting system, SubjectObserver!(Display, Sensor) for data acquisition system, SubjectObserver!(Mailbox, Topic) for message delivery system and so on)). Class Subject in template SubjectObjserver may be inherited from another useful class (Serializabe, Loggable, Dumpable or something else). This means that in the following case:
> 
> class Account : SubjectObserver!(Notificator, Account).Subject { ... }
> class Topic : SubjectObserver!(Mailbox, Topic).Subject { ... }
> 
> classes Account and Topic will be automatically derived from Serializable (Loggable, Dumpable, ...) too.
> 
> In case of:
> 
> class Account {
>   mixin Subject!(Notificator, Account);
>   ...
> }
> class Topic {
>   mixin Subject!(Mailbox, Topic);
>   ...
> }
> 
> it is neccessary to derive Account and Topic from Serializable (Loggable, Dumpable, ...) manually.
I see, you're right. :)

As a side not, there's one pattern which could be interesting in this kind of situation:

template Subject(O, S)
{
    ... // Implementation details

    alias Tuple!(Loggable, Dumpable, ...) ImplementedInterfaces;
}

...

class Account : Subject!(Notifier, Account).ImplementedInterfaces {
    mixin Subject!(Notifier, Account);
}

  -- Reiner
May 27, 2007
On Sun, 27 May 2007 11:24:40 +0400, Reiner Pope <some@address.com> wrote:

> As a side not, there's one pattern which could be interesting in this kind of situation:
>
> template Subject(O, S)
> {
>      ... // Implementation details
>
>      alias Tuple!(Loggable, Dumpable, ...) ImplementedInterfaces;
> }
>
> ...
>
> class Account : Subject!(Notifier, Account).ImplementedInterfaces {
>      mixin Subject!(Notifier, Account);
> }

Wow! Thank!
It's very interesting idea.

-- 
Regards,
Yauheni Akhotnikau
May 29, 2007
On Sat, 26 May 2007 00:30:11 +0400, Jari-Matti Mäkelä <jmjmak@utu.fi.invalid> wrote:

> Can you show how this would work if there were multiple subclasses
> of 'Subject' and 'Observer'? (for example multiple sensor types in the
> SensorReader example) Does it require language support for multiple
> dispatch then?

More complex example is here: http://eao197.narod.ru/scala/AbstractTypesDemo.scala.html (thanks to aka50!)
I've add yet another descendant of Sensor -- CalibrateableSensor with can use Calibrator for adjusting his values. Display can show values from Sensor and from CalibrateableSensor, but Calibrator can work only with CalibrateableSensor.

Here is some difficalty in extending classes with selftypes by inheritance in Scala. It is impossible to simple inherit CalbrateableSensor from Sensor and add data necessary for calibration support to it. That is because it is necessary to define additional trait CalibrateableEntity and use it in 'requires' clause for CalibrateableSensor trait.

In D construct 'class A is B' for classes in template may be more useful and less restricted:

template SubjectObserver(S,O) {
  class Subject is S { ... }
  class Observer { ... }
}

template AbstractSensorReader(S,D) {
  class Sensor is S : SubjectObserver!(Sensor, D).Subject { ... }
  class Display : SubjectObserver!(S, D).Observer { ... }

  class CalibrateableSensor : Sensor { ... }
  class Calibrator { ... }
}

without need of additional interfaces an so on.

-- 
Regards,
Yauheni Akhotnikau
Next ›   Last »
1 2
Top | Discussion index | About this forum | D home