Jump to page: 1 2
Thread overview
Real OOP with D
Aug 17, 2015
Ozan
Aug 17, 2015
Ali Çehreli
Aug 18, 2015
Ozan
Aug 18, 2015
Kagamin
Aug 18, 2015
Kagamin
Aug 17, 2015
Rikki Cattermole
Aug 18, 2015
Ozan
Aug 17, 2015
BBasile
Aug 18, 2015
Ozan
Aug 18, 2015
BBasile
Aug 18, 2015
Caspar
August 17, 2015
Hi

Working with objectoriented concepts results often in large trees of related classes. Every instance of a class knows his methods and data.  An example like following would work:

import std.stdio;
class Family { }
class Dad : Family { void greeting() { writeln("I'm dad"); } }
class Boy : Family { void greeting() { writeln("I'm daddy's boy"); } }
void main() {
writeln("Father and son");
Dad father = new Dad;
Family son = new Boy;
father.greeting;
son.greeting;
}

The critical point is using a variable of type Family for an instance of Boy. Class Family covers the greeting method of Boy. In real OOP that would not be a problem, because the access point of view starts with the object. In D, it starts with the class definition.

Is there any way to get real OOP with D?

Regards,  Ozan
August 17, 2015
On 08/16/2015 10:57 PM, Ozan wrote:

> Working with objectoriented concepts results often in large trees of
> related classes. Every instance of a class knows his methods and data.
> An example like following would work:
>
> import std.stdio;
> class Family { }

From the way you use it below, a better name for that class would be FamilyMember but I get the point.

> class Dad : Family { void greeting() { writeln("I'm dad"); } }
> class Boy : Family { void greeting() { writeln("I'm daddy's boy"); } }
> void main() {
> writeln("Father and son");
> Dad father = new Dad;
> Family son = new Boy;
> father.greeting;
> son.greeting;

What you mean is that the call above causes a compilation error:

Error: no property 'greeting' for type 'deneme.Family'

> }
>
> The critical point is using a variable of type Family for an instance of
> Boy. Class Family covers the greeting method of Boy. In real OOP that
> would not be a problem, because the access point of view starts with the
> object.

My experience with OOP is limited to C++ and D. I think what you are describing is how dynamically typed languages work. It is impossible in compiled languages like C++ and D. When a type is used in an expression, the compiler ensures that the call is bound to a function.

> In D, it starts with the class definition.

Actually, 'interface' is a better fit in most cases:

interface FamilyMember
{
    // ...
}

class Dad : FamilyMember
{
    // ...
}

> Is there any way to get real OOP with D?
>
> Regards,  Ozan

Ali

August 17, 2015
On 17/08/2015 5:57 p.m., Ozan wrote:
> Hi
>
> Working with objectoriented concepts results often in large trees of
> related classes. Every instance of a class knows his methods and data.
> An example like following would work:
>
> import std.stdio;
> class Family { }
> class Dad : Family { void greeting() { writeln("I'm dad"); } }
> class Boy : Family { void greeting() { writeln("I'm daddy's boy"); } }
> void main() {
> writeln("Father and son");
> Dad father = new Dad;
> Family son = new Boy;
> father.greeting;
> son.greeting;
> }
>
> The critical point is using a variable of type Family for an instance of
> Boy. Class Family covers the greeting method of Boy. In real OOP that
> would not be a problem, because the access point of view starts with the
> object. In D, it starts with the class definition.
>
> Is there any way to get real OOP with D?
>
> Regards,  Ozan

import std.stdio;
abstract class Family { void greeting(); }
class Dad : Family { void greeting() { writeln("I'm dad"); } }
class Boy : Family { void greeting() { writeln("I'm daddy's boy"); } }

void main() {
	Family dad = new Dad;
	Family boy = new Boy;
	dad.greeting;
	boy.greeting;
}

I'm confused how this isn't real OOP?
August 17, 2015
On Monday, 17 August 2015 at 05:57:52 UTC, Ozan wrote:
> Hi
>
> Working with objectoriented concepts results often in large trees of related classes. Every instance of a class knows his methods and data.  An example like following would work:
>
> import std.stdio;
> class Family { }
> class Dad : Family { void greeting() { writeln("I'm dad"); } }
> class Boy : Family { void greeting() { writeln("I'm daddy's boy"); } }
> void main() {
> writeln("Father and son");
> Dad father = new Dad;
> Family son = new Boy;
> father.greeting;
> son.greeting;
> }
>
> The critical point is using a variable of type Family for an instance of Boy. Class Family covers the greeting method of Boy. In real OOP that would not be a problem, because the access point of view starts with the object. In D, it starts with the class definition.
>
> Is there any way to get real OOP with D?
>
> Regards,  Ozan

Can you name an OOP oriented language that allows this ? Your example is eroneous OOP.
The 2 other answers you 've got (the first using an interface and the second using an abstract class) are valid OOP.

One of the fundamental concept OOP is that a function defined in a class exists also  in its subclasses. So how do you expect `greeting()` to exist in Family if it's only defined in its sub-classes ?

You can verify that with the 'Liskov substitution principle' (https://en.wikipedia.org/wiki/Liskov_substitution_principle).
Actually your sample violates this principle.
August 18, 2015
On Monday, 17 August 2015 at 06:08:35 UTC, Ali Çehreli wrote:
> On 08/16/2015 10:57 PM, Ozan wrote:
>
[...]
>
> From the way you use it below, a better name for that class would be FamilyMember but I get the point.
Yes,  you're right.
>
[...]
> > father.greeting;
> > son.greeting;
>
> What you mean is that the call above causes a compilation error:
>
> Error: no property 'greeting' for type 'deneme.Family'
>
> > }
> >
[...]
>
> My experience with OOP is limited to C++ and D. I think what you are describing is how dynamically typed languages work. It is impossible in compiled languages like C++ and D. When a type is used in an expression, the compiler ensures that the call is bound to a function.
>
> > In D, it starts with the class definition.
>
> Actually, 'interface' is a better fit in most cases:
>
> interface FamilyMember
> {
>     // ...
> }
>
> class Dad : FamilyMember
> {
>     // ...
> }
>
[...]
>
> Ali

Interfaces are very helpful to avoid large inheritance trees in OOP. On the other hand,  there are not designed as workarounds for OOP implementation problems.
The kind of OOP in D is a classical way to handle it. Dynamic languages tries to close the gap between theoretical and practical OOP for the price of speed.
I think that Adam's jsvar idea is a great way to bring more flexibility into D. The same in OOP would be also great.

Regards,  Ozan

August 18, 2015
On Monday, 17 August 2015 at 06:10:38 UTC, Rikki Cattermole wrote:
> On 17/08/2015 5:57 p.m., Ozan wrote:
>> Hi
>>
[...]
>
> import std.stdio;
> abstract class Family { void greeting(); }
> class Dad : Family { void greeting() { writeln("I'm dad"); } }
> class Boy : Family { void greeting() { writeln("I'm daddy's boy"); } }
>
> void main() {
> 	Family dad = new Dad;
> 	Family boy = new Boy;
> 	dad.greeting;
> 	boy.greeting;
> }
>
> I'm confused how this isn't real OOP?

Replace 'real' with 'theoretical' OOP. Every instance of a class (object) is like an independent black box. Every public message (method / function) of the class definition could be called when ever you want. Variables are like pointers to objects. With inheritance and overriding you're losing in class type implementations of OOP a lot of 'theoretical'  flexibility. I was asking for a possibility to avoid this.

Regards Ozan
August 18, 2015
On Monday, 17 August 2015 at 06:59:51 UTC, BBasile wrote:
> On Monday, 17 August 2015 at 05:57:52 UTC, Ozan wrote:
>> Hi
[...]
>>
>> Is there any way to get real OOP with D?
>>
>> Regards,  Ozan
>
> Can you name an OOP oriented language that allows this ? Your example is eroneous OOP.
> The 2 other answers you 've got (the first using an interface and the second using an abstract class) are valid OOP.
>
> One of the fundamental concept OOP is that a function defined in a class exists also  in its subclasses. So how do you expect `greeting()` to exist in Family if it's only defined in its sub-classes ?
>
> You can verify that with the 'Liskov substitution principle' (https://en.wikipedia.org/wiki/Liskov_substitution_principle).
> Actually your sample violates this principle.

Languages like Groovy or JavaScript (with the help of frameworks ;-)
And I believe many more the newer ones.  But that's not the point.

And... This was not a criticism against D (... "bad D, has no understanding of OOP. Boahh"  ;-)
It was only a question about handling of a typical OOP problem in a class-typed implementation of OOP like D has. Thanks to every existing or new creative programming language, today we have so many other ways to solve our programming problems.

Regards Ozan
August 18, 2015
On Tuesday, 18 August 2015 at 06:27:53 UTC, Ozan wrote:
> On Monday, 17 August 2015 at 06:59:51 UTC, BBasile wrote:
>> On Monday, 17 August 2015 at 05:57:52 UTC, Ozan wrote:
>>> Hi
> [...]
>>>
>>> Is there any way to get real OOP with D?
>>>
>>> Regards,  Ozan
>>
>> Can you name an OOP oriented language that allows this ? Your example is eroneous OOP.
>> The 2 other answers you 've got (the first using an interface and the second using an abstract class) are valid OOP.
>>
>> One of the fundamental concept OOP is that a function defined in a class exists also  in its subclasses. So how do you expect `greeting()` to exist in Family if it's only defined in its sub-classes ?
>>
>> You can verify that with the 'Liskov substitution principle' (https://en.wikipedia.org/wiki/Liskov_substitution_principle).
>> Actually your sample violates this principle.
>
> Languages like Groovy or JavaScript (with the help of frameworks ;-)
> And I believe many more the newer ones.  But that's not the point.
>
> And... This was not a criticism against D (... "bad D, has no understanding of OOP. Boahh"  ;-)
> It was only a question about handling of a typical OOP problem in a class-typed implementation of OOP like D has. Thanks to every existing or new creative programming language, today we have so many other ways to solve our programming problems.
>
> Regards Ozan

You example is not valid strongly-typed OOP. In D you could do something similar but not with the OO paradigm but rather with compile-time refexion (introspection):

---
import std.stdio;

static bool isFamilyMember(T)()
{
    import std.traits: isCallable;
    return __traits(hasMember, T, "greeting");
}

void FamilyMemberSayHello(T)(ref T t)
{
    static if (isFamilyMember!T)
        t.greeting;
}

struct Dad{
    void greeting(){"hello from a Dad".writeln;}
}

struct Boy{
    void greeting(){"hello from a Boy".writeln;}
}

struct IdiotDuBled{}

void main()
{
    auto dad = new Dad;
    auto boy = new Boy;
    auto idiotDuBled = new IdiotDuBled;

    FamilyMemberSayHello(dad);
    FamilyMemberSayHello(boy);
    FamilyMemberSayHello(idiotDuBled);
}
---

The idea is rather to check at compile time if a variable will have the "trait" which characterizes a FamilyMember, without using inheritence.
August 18, 2015
On Tuesday, 18 August 2015 at 06:03:09 UTC, Ozan wrote:
> I think that Adam's jsvar idea is a great way to bring more flexibility into D. The same in OOP would be also great.

Dynamic typing in D can be emulated in the same way jsvar and Variant do it. If jsvar doesn't support it, you can look into libraries like luad, which AFAIK can generate dynamic wrappers for static types, I suppose there was something similar for IDispatch.
August 18, 2015
On Tuesday, 18 August 2015 at 06:03:09 UTC, Ozan wrote:
> I think that Adam's jsvar idea is a great way to bring more flexibility into D. The same in OOP would be also great.

Looks like jsvar can invoke opCall method for wrapped object: https://github.com/adamdruppe/arsd/blob/master/jsvar.d#L729 you can extend it to support invocation of other methods.
« First   ‹ Prev
1 2