Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 18, 2007 how to change attribute in descendant? | ||||
---|---|---|---|---|
| ||||
Hello. I need declare some base class A with general functionality, then more special descendants AA and AB. "A" class have some fields, that i don't want "show", i make it protected. Then in some descendant i need "open" it. I need change it from "protected" to "public". In Delphi i just redeclare it in descendant, but in "public" section. Delphi allow change visibility of class members from low to higher. Private->protected->public. How i can do this in D? /********* test.d ********/ import std.stdio; //base class with general code abstract class Animal { protected int legsCount; protected int poisonStrength; public bool canWalk() { return legsCount>0; } public bool canKill() { return poisonStrength>0; } } //tiger = animal with legs without poison class Tiger : Animal { public int legsCount; } //snake = animal without legs with poison class Snake : Animal { public int poisonStrength; } void main() { Tiger t = new Tiger; t.legsCount = 4; writefln("tiger: legs=%d, canWalk=%d, canKill=%d", t.legsCount, t.canWalk, t.canKill); Snake s = new Snake; s.poisonStrength = 100; writefln("snake: poison=%d, canWalk=%d, canKill=%d", s.poisonStrength, s.canWalk, s.canKill); } output: tiger: legs=4, canWalk=0, canKill=0 snake: poison=100, canWalk=0, canKill=0 |
January 18, 2007 Re: how to change attribute in descendant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to novice2 | novice2 wrote: > Hello. > I need declare some base class A with general functionality, then > more special descendants AA and AB. > "A" class have some fields, that i don't want "show", i make it > protected. Then in some descendant i need "open" it. I need change > it from "protected" to "public". > In Delphi i just redeclare it in descendant, but in "public" > section. Delphi allow change visibility of class members from low > to higher. Private->protected->public. It's funny you post this now. I had a co-worker who had the same exact same problem in Java yesterday. :) In short: fields cannot be overridden in the same way that methods can. Even though the compiler lets you do this: class A{ char[] name = "Class A"; } class B:A{ char[] name = "Class B"; } ... it is considered bad form. Avoid doing this if you can. A matching member name, instead of overriding the declaration within the super-class, subtly *masks* the super-class' declaration instead. Technically, both fields co-exist, side-by-side. This is because the compiler treats all member declarations the same, regardless if they match a super-class' member name (regardless of type). Obviously, this can become very confusing: void main(){ A a = new A(); B b = new B(); writefln("A: %s",a.name); // prints: Class A writefln("B: %s",b.name); // prints: Class B writefln("B: %s",(cast(A)b).name); // prints: Class A <-- A.name is still there, and is not overridden } The way to fix this is pretty straightforward. Just use one field only for any such purpose: class A{ char[] name; this(){ name = "Class A"; } } class B:A{ this(){ name = "Class B"; } } This way, every 'A' and every subclass of 'A' will have the same 'name' field. It then down to each subclass to change the value of 'name' as is appropriate. In the case of your program, where you try to 'open' things up as you go down the hierarchy, you can do something like this: class A{ private char[] myName; protected char[] name(){ return myName; } this(){ myName= "Class A"; } } class B:A{ public char[] name(){ return myName; } this(){ myName= "Class B"; } } Again, since only methods can be overridden, this is the only way to go. This example also demonstrates D's property syntax, which is a nice concession for situations like this. Try using this snippet with the "void main()" snippet above. :) -- - EricAnderton at yahoo |
January 18, 2007 Re: how to change attribute in descendant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pragma | Pragma wrote: > This example also demonstrates D's property syntax, which is a nice concession for situations like this. Try using this snippet with the "void main()" snippet above. :) Eric, do you happen to know, if it's possible to do the opposite - i.e. make public methods private by using private/protected inheritance? The spec says (http://www.digitalmars.com/d/class.html): InterfaceClass: Identifier Protection Identifier Protection: private package public export But what does it mean? I've asked this a few times before (nobody answered). The compiler just bypasses the protection attributes. I think other than public inheritance is anyway bad in D, especially when the protection is used with interfaces. |
January 18, 2007 Re: how to change attribute in descendant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pragma | == Quote from Pragma (ericanderton@yahoo.removeme.com)'s article > In short: fields cannot be overridden in the same way that methods can. Even though the compiler lets you do this: Thank you for explanation. Delphi ability knowing confuse me. |
January 18, 2007 Re: how to change attribute in descendant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jari-Matti Mäkelä | Jari-Matti Mäkelä wrote: > Pragma wrote: >> This example also demonstrates D's property syntax, which is a nice >> concession for situations like this. Try using this snippet with the >> "void main()" snippet above. :) > > Eric, do you happen to know, if it's possible to do the opposite - i.e. > make public methods private by using private/protected inheritance? The > spec says (http://www.digitalmars.com/d/class.html): > > InterfaceClass: > Identifier > Protection Identifier > > Protection: > private > package > public > export > > But what does it mean? I've asked this a few times before (nobody > answered). The compiler just bypasses the protection attributes. I think > other than public inheritance is anyway bad in D, especially when the > protection is used with interfaces. (I'm assuming that you're coming from a novice background here - my apologies if this is not the case) Sadly the documentation is kind of in an "expert mode" state at the moment. In many places, it assumes that you're already familiar with C++ or Java - most of us here are, so we mentally fill in these gaps without realizing they're missing! *ahem* anyway, the protection attributes break down like so: public - accessible by all protected - accessible by the declaring scope and any scopes that inherit it private - only accessible by the declaring scope package - accessible by all, *within the same package* export - accessible by external programs and libraries (it's of out of place in this discussion) ...where a scope is a module, interface, class or struct. Well one thing that isn't illustrated in the grammar (quoted above) is that 'public' is implied for anything accessed from within the same module - perhaps this is what you're seeing when the compiler 'bypasses' things? You have to break your classes and interfaces out into distinct files for these attributes to be enforced as you'd expect. While I know this seems odd, it's much better than what Java or C++ would have to do to achieve the same effect. From the perspective of someone (me) who writes libraries in D, it's a help and not a hindrance. -- - EricAnderton at yahoo |
January 18, 2007 Re: how to change attribute in descendant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pragma | Pragma kirjoitti: > Jari-Matti Mäkelä wrote: >> Eric, do you happen to know, if it's possible to do the opposite - i.e. make public methods private by using private/protected inheritance? The spec says (http://www.digitalmars.com/d/class.html): >> >> InterfaceClass: >> Identifier >> Protection Identifier >> >> Protection: >> private >> package >> public >> export >> >> But what does it mean? I've asked this a few times before (nobody answered). The compiler just bypasses the protection attributes. I think other than public inheritance is anyway bad in D, especially when the protection is used with interfaces. > > (I'm assuming that you're coming from a novice background here - my apologies if this is not the case) Sorry - the question was a bit naive. What I meant was that why isn't it working. > > ...where a scope is a module, interface, class or struct. > > Well one thing that isn't illustrated in the grammar (quoted above) is that 'public' is implied for anything accessed from within the same module Yes. >- perhaps this is what you're seeing when the compiler 'bypasses' > things? No. You see, if I read and quess the grammar correctly, some of this should work: module aaa; interface A { public void a(); // the public is of course implied here } class B { public void b() { } } --- module bbb class C : private A, private B // the problem is this part of the grammar { private void a() { } } --- module ccc void main() { auto a = new C(); a.a(); // should raise a compile time error ? a.b(); // should raise a compile time error } --- Here's the same code in standard C++ and it correctly raises a compile time error: #include <stdio.h> class A { public: void a() { printf("hello"); } }; class B: private A { }; int main() { B *b = new B(); b->a(); return 0; } > You have to break your classes and interfaces out into distinct files for these attributes to be enforced as you'd expect. But it doesn't help. |
January 18, 2007 Re: how to change attribute in descendant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jari-Matti Mäkelä | "Jari-Matti Mäkelä" <jmjmak@utu.fi.invalid> wrote in message news:eooa7j$1bie$1@digitaldaemon.com... > Sorry - the question was a bit naive. What I meant was that why isn't it working. Since the spec never says anything about protection on base classes/interfaces, and since it's been asked about many times, I guess it's one of two things: (1) a vestige from a long, long time ago when these were planned to work, but were never implemented, or (2) just there for future expansion. It'd be interesting to see what code is there for it in the compiler frontend. |
January 19, 2007 Re: how to change attribute in descendant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jarrett Billingsley | Jarrett Billingsley kirjoitti:
> "Jari-Matti Mäkelä" <jmjmak@utu.fi.invalid> wrote in message news:eooa7j$1bie$1@digitaldaemon.com...
>
>> Sorry - the question was a bit naive. What I meant was that why isn't it working.
>
> Since the spec never says anything about protection on base classes/interfaces, and since it's been asked about many times, I guess it's one of two things: (1) a vestige from a long, long time ago when these were planned to work, but were never implemented, or (2) just there for future expansion. It'd be interesting to see what code is there for it in the compiler frontend.
They have been a very long time there. I suppose Walter has copied them from the C++ spec and forgotten a bit later.
I don't mind even if D won't support them, since Java also has plain public inheritance and it's still usable as a language. Most of the information hiding can be done by abstracting the classes more. Private inheritance at least might cause some odd corner cases on runtime when used in conjunction with the implicit friend syntax within the same module and interfaces.
|
January 19, 2007 Re: how to change attribute in descendant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to novice2 | novice2 Wrote:
> Then in some descendant i need "open" it.
This seems to be a clear sign of misunderstanding/misusing object orientation.
Descendendants, as you say, need to be like ancestors without any restrictions. Thus there cannot be any need to "open" any closed "attributes".
IMO you mean something like this:
class Animal{
Attribute walk=null, kill=null;
bool canWalk(){ return walk !is null;}
bool canKill(){ return kill !is null;}
}
class Tiger:Animal{
this(){ walk= new Walk(4);}
}
class Walk:Attribute{
int legs;
this( int count){ legs= count; };
}
class Attribute{}
void main(){
Tiger t= new Tiger;
writefln( t.walk.legs, t.canWalk, t.canKill);
...
|
January 19, 2007 Re: how to change attribute in descendant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to %u | "%u" <u@infearof.spm> wrote in message news:eop4o3$2mq1$1@digitaldaemon.com... > novice2 Wrote: > >> Then in some descendant i need "open" it. > This seems to be a clear sign of misunderstanding/misusing object > orientation. > Descendendants, as you say, need to be like ancestors without any > restrictions. Thus there cannot be any need to "open" any closed > "attributes". OT: Mr/s. %u, would you please, please use a newsreader? There is a bug in the web interface which messes up your name when you post, and it's really disconcerting not knowing your name (and indeed, whether or not all the posts by %u are by the same author). |
Copyright © 1999-2021 by the D Language Foundation