Jump to page: 1 2
Thread overview
Object oriented programming and interfaces
Dec 04, 2017
Dirk
Dec 04, 2017
Craig Dillabaugh
Dec 04, 2017
Adam D. Ruppe
Dec 04, 2017
Jacob Carlborg
Dec 05, 2017
Dirk
Dec 05, 2017
Andrea Fontana
Dec 05, 2017
Daniel Kozak
Dec 05, 2017
bauss
Dec 05, 2017
Adam D. Ruppe
Dec 05, 2017
Jesse Phillips
December 04, 2017
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?
December 04, 2017
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. See #6 at:

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; }
}
December 04, 2017
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.
December 04, 2017
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
December 04, 2017
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 );

December 05, 2017
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?
December 05, 2017
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?
December 05, 2017
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?
>


December 05, 2017
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.
December 05, 2017
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.
« First   ‹ Prev
1 2