digitalmars.D.learn - Real OOP with D
- Ozan (23/23) Aug 16 2015 Hi
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (19/40) Aug 16 2015 From the way you use it below, a better name for that class would be
- Ozan (15/40) Aug 17 2015 Yes, you're right.
- Rikki Cattermole (12/33) Aug 16 2015 import std.stdio;
- Ozan (10/25) Aug 17 2015 Replace 'real' with 'theoretical' OOP. Every instance of a class
- BBasile (12/35) Aug 16 2015 Can you name an OOP oriented language that allows this ? Your
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
Aug 16 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, OzanAli
Aug 16 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 { // ... }AliInterfaces 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
Aug 17 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.
Aug 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.
Aug 18 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, Ozanimport 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?
Aug 16 2015
On Monday, 17 August 2015 at 06:10:38 UTC, Rikki Cattermole wrote:On 17/08/2015 5:57 p.m., Ozan wrote:[...]Hiimport 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
Aug 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, OzanCan 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.
Aug 16 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:[...]HiLanguages 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 OzanIs there any way to get real OOP with D? Regards, OzanCan 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.
Aug 17 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: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.On Monday, 17 August 2015 at 05:57:52 UTC, Ozan wrote:[...]HiLanguages 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 OzanIs there any way to get real OOP with D? Regards, OzanCan 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.
Aug 18 2015
On Tuesday, 18 August 2015 at 07:19:02 UTC, BBasile wrote:On Tuesday, 18 August 2015 at 06:27:53 UTC, Ozan wrote:I believe D allows what you want to do using generic programming. Being a compiled and strongly typed language, the information about the type, needs to be available during compilation, but this makes no difference from a theoretic OOP view. BBasiles example can also be done without the trait. Then the check for greeting() will be done by the compiler. void FamilyMemberSayHello(T)(ref T 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); //will not compile } The OOP Model of D is fairly close to that of Eiffel which I consider pretty pure Object Oriented. The only exception is multiple inheritance, which I do not miss at all. In my Opinion D is a great language for Object Oriented Design and Programming. It awesomely supports Contracts and Constraint Generics, which many languages lack. I never missed multiple inheritance, as I was able to cover all my use cases with mixins. The support for functional programming and CTFE allows to elegantly handle the cases, where inheritance based OOP feels awkward. Actually I urge all the people who say: "Smalltalk was the last (only) good OOP language!" to try out D.On Monday, 17 August 2015 at 06:59:51 UTC, BBasile wrote: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.On Monday, 17 August 2015 at 05:57:52 UTC, Ozan wrote:[...]HiLanguages 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 OzanIs there any way to get real OOP with D? Regards, OzanCan 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.
Aug 18 2015