www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Object oriented programming and interfaces

reply Dirk <dirk mail.com> writes:
Hi!

I defined an interface:

interface Medoid {
     float distance( Medoid other );
     uint id() const  property;
}

and a class implementing that interface:

class Item : Medoid {
     float distance( Item i ) {...}
     uint id() const  property {...}
}

The compiler says:
Error: class Item interface function 'float distance(Medoid 
other)' is not implemented

Is there a way to implement the Item.distance() member function 
taking any object whose class is Item?
Dec 04 2017
next sibling parent Craig Dillabaugh <craig.dillabaugh gmail.com> writes:
On Monday, 4 December 2017 at 20:43:27 UTC, Dirk wrote:
 Hi!

 I defined an interface:

 interface Medoid {
     float distance( Medoid other );
     uint id() const  property;
 }

 and a class implementing that interface:

 class Item : Medoid {
     float distance( Item i ) {...}
     uint id() const  property {...}
 }

 The compiler says:
 Error: class Item interface function 'float distance(Medoid 
 other)' is not implemented

 Is there a way to implement the Item.distance() member function 
 taking any object whose class is Item?
Interfaces are expected to implement static or final functions. https://dlang.org/spec/interface.html interface Medoid { static float distance( Medoid other ); uint id() const property; } class Item : Medoid { static float distance( Item i ) { return 0.0f; } uint id() const property { return 1; } }
Dec 04 2017
prev sibling next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 4 December 2017 at 20:43:27 UTC, Dirk wrote:
 interface Medoid {
     float distance( Medoid other );
     uint id() const  property;
 }

 and a class implementing that interface:

 class Item : Medoid {
     float distance( Item i ) {...}
     uint id() const  property {...}
 }

 The compiler says:
 Error: class Item interface function 'float distance(Medoid 
 other)' is not implemented

 Is there a way to implement the Item.distance() member function 
 taking any object whose class is Item?
So what would happen there if someone did: Medoid i = new Item(); i.distance(new OtherMedoid()); What does it call there? The OtherMedoid isn't an Item, so your Item.distance method wouldn't work... meaning it didn't actually implement the interface. Item.distance CAN take any Item, that function is legal... it just doesn't impelment the interface since it isn't broad enough to take anything the interface can take. So remove it from the interface or implement a generic version too.
Dec 04 2017
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2017-12-04 21:43, Dirk wrote:
 Hi!
 
 I defined an interface:
 
 interface Medoid {
      float distance( Medoid other );
      uint id() const  property;
 }
 
 and a class implementing that interface:
 
 class Item : Medoid {
      float distance( Item i ) {...}
      uint id() const  property {...}
 }
 
 The compiler says:
 Error: class Item interface function 'float distance(Medoid other)' is 
 not implemented
 
 Is there a way to implement the Item.distance() member function taking 
 any object whose class is Item?
I don't think so. In the "Item" class you have declared "distance" to take an instance of "Item", which is more specialized than "Medoid". If an instance of "Item" is used through the "Medoid" interface, that interface allows to pass any object to the "distance" method that implements the "Medoid" interface. That can be a different class than "Medoid". You could add an overload that takes an instance of "Item", if that helps. -- /Jacob Carlborg
Dec 04 2017
prev sibling next sibling parent reply A Guy With a Question <aguywithanquestion gmail.com> writes:
On Monday, 4 December 2017 at 20:43:27 UTC, Dirk wrote:
 Hi!

     float distance( Medoid other );
     float distance( Item i ) {...}

The two signatures need to be the same. I think this is true of 
most OOP languages. Have them both be:

float distance( Medoid other );
Dec 04 2017
parent reply Dirk <dirk mail.com> writes:
The distance function is implementation dependend and can only be 
computed between two objects of the same class (in this example 
the class is Item).

My goal is to write a module for a k-medoids clustering 
algorithm. The class MedoidClassification shall be able to 
partition a list of objects from the same class, which implement 
the Medoid interface.

My current approach is this (which does not work):

interface Medoid {
     float distance( Medoid other );
     uint id() const  property;
}

class Item : Medoid {
     float distance( Item m ) {...}
     uint id() const  property {...}
}

class MedoidClassification {
     this( Medoid[] list ) {...}
     Medoid[][] getClusters() {...}
}

void main() {
     Item[10] items;
     auto mc = MedoidClassification( items );
}


What would be a good way to implement this?
Dec 04 2017
next sibling parent Andrea Fontana <nospam example.com> writes:
On Tuesday, 5 December 2017 at 07:47:32 UTC, Dirk wrote:
 What would be a good way to implement this?
Did you tried to use introspection?
Dec 05 2017
prev sibling next sibling parent reply Daniel Kozak <kozzi11 gmail.com> writes:
You can do something like this:

interface Medoid(T) {
    float distance( T other );
    uint id() const  property;
}

class Item : Medoid!(Item) {
    float distance( Item m ) { return 0.;}
    uint id() const  property { return 1; }
}

class MedoidClassification {
    this(T:Medoid!T)(T[] list) {}
    //Medoid[][] getClusters() {...}
}

void main() {
    auto items = new Item[10];
    auto mc = new MedoidClassification( items );
}

On Tue, Dec 5, 2017 at 8:47 AM, Dirk via Digitalmars-d-learn <
digitalmars-d-learn puremagic.com> wrote:

 The distance function is implementation dependend and can only be computed
 between two objects of the same class (in this example the class is Item).

 My goal is to write a module for a k-medoids clustering algorithm. The
 class MedoidClassification shall be able to partition a list of objects
 from the same class, which implement the Medoid interface.

 My current approach is this (which does not work):

 interface Medoid {
     float distance( Medoid other );
     uint id() const  property;
 }

 class Item : Medoid {
     float distance( Item m ) {...}
     uint id() const  property {...}
 }

 class MedoidClassification {
     this( Medoid[] list ) {...}
     Medoid[][] getClusters() {...}
 }

 void main() {
     Item[10] items;
     auto mc = MedoidClassification( items );
 }


 What would be a good way to implement this?
Dec 05 2017
parent bauss <jj_1337 live.dk> writes:
On Tuesday, 5 December 2017 at 08:08:55 UTC, Daniel Kozak wrote:
 You can do something like this:

 interface Medoid(T) {
     float distance( T other );
     uint id() const  property;
 }

 class Item : Medoid!(Item) {
     float distance( Item m ) { return 0.;}
     uint id() const  property { return 1; }
 }

 class MedoidClassification {
     this(T:Medoid!T)(T[] list) {}
     //Medoid[][] getClusters() {...}
 }

 void main() {
     auto items = new Item[10];
     auto mc = new MedoidClassification( items );
 }

 On Tue, Dec 5, 2017 at 8:47 AM, Dirk via Digitalmars-d-learn < 
 digitalmars-d-learn puremagic.com> wrote:

 The distance function is implementation dependend and can only 
 be computed between two objects of the same class (in this 
 example the class is Item).

 My goal is to write a module for a k-medoids clustering 
 algorithm. The class MedoidClassification shall be able to 
 partition a list of objects from the same class, which 
 implement the Medoid interface.

 My current approach is this (which does not work):

 interface Medoid {
     float distance( Medoid other );
     uint id() const  property;
 }

 class Item : Medoid {
     float distance( Item m ) {...}
     uint id() const  property {...}
 }

 class MedoidClassification {
     this( Medoid[] list ) {...}
     Medoid[][] getClusters() {...}
 }

 void main() {
     Item[10] items;
     auto mc = MedoidClassification( items );
 }


 What would be a good way to implement this?
This still defeats the purpose of having multiple Medoid types, as each Medoid is still specified with a specific type.
Dec 05 2017
prev sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 5 December 2017 at 07:47:32 UTC, Dirk wrote:
 The distance function is implementation dependend and can only 
 be computed between two objects of the same class (in this 
 example the class is Item).
Just don't put it in the interface. Leave it in the individual classes with the stricter definition. Or, as I said before, implement the interface by asking the question: what if you call Item.distance (NotAnItem)? Maybe you could throw an exception or return NaN to show this is an invalid comparison. But if it is in the interface, you MUST answer that question somehow. --- interface Medoid { float distance(Medoid other); } class Item { float distance(Medoid other) { if(auto item = cast(Item) other) { // it is an item, implement comparison here } else { return float.nan; // invalid comparison } } } --- Tip: you can generically test that two objects are of the same class through their interfaces by checking: if(typeid(cast(Object) o1) == typeid(cast(Object) o2)) { // same class } else { // same interface, but different class } Might be useful for your classifier, though checking the nan of distance might be good too.
Dec 05 2017
prev sibling next sibling parent Jesse Phillips <Jesse.K.Phillips+D gmail.com> writes:
On Monday, 4 December 2017 at 20:43:27 UTC, Dirk wrote:
 Hi!

 I defined an interface:

 interface Medoid {
     float distance( Medoid other );
     uint id() const  property;
 }

 and a class implementing that interface:

 class Item : Medoid {
     float distance( Item i ) {...}
     uint id() const  property {...}
 }

 The compiler says:
 Error: class Item interface function 'float distance(Medoid 
 other)' is not implemented

 Is there a way to implement the Item.distance() member function 
 taking any object whose class is Item?
I think everyone here has missed the reason. The problem is that a derived type can do more, the interface only allows for two method calls while the class could theoretically do more. If the compiler allowed the class it would let you access functions and members not available to the interfaces, and the function would still be passed a Medoid. You could make a cast within your function, but then you're still really not handling the interface but that at least would be clear in the code rather than the compiler hiding it by ignoring the problem.
Dec 05 2017
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 12/4/17 3:43 PM, Dirk wrote:
 Hi!
 
 I defined an interface:
 
 interface Medoid {
      float distance( Medoid other );
      uint id() const  property;
 }
 
 and a class implementing that interface:
 
 class Item : Medoid {
      float distance( Item i ) {...}
      uint id() const  property {...}
 }
 
 The compiler says:
 Error: class Item interface function 'float distance(Medoid other)' is 
 not implemented
 
 Is there a way to implement the Item.distance() member function taking 
 any object whose class is Item?
You are thinking about covariance and contravariance. In D, only the return value can work with covariance: interface Medoid { Medoid getIt(); } class Item : Medoid { Item getIt() { return this; } } D does not support contravariance on parameters. And in any case you have it backwards. A derived override could take a base type, but not a more specific type, for the reasons Adam outlined. -Steve
Dec 05 2017