www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - how to change attribute in descendant?

reply novice2 <sorry noem.ail> writes:
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
Jan 18 2007
next sibling parent reply Pragma <ericanderton yahoo.removeme.com> writes:
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
Jan 18 2007
next sibling parent reply =?UTF-8?B?SmFyaS1NYXR0aSBNw6RrZWzDpA==?= <jmjmak utu.fi.invalid> writes:
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.
Jan 18 2007
parent reply Pragma <ericanderton yahoo.removeme.com> writes:
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
Jan 18 2007
parent reply =?UTF-8?B?SmFyaS1NYXR0aSBNw6RrZWzDpA==?= <jmjmak utu.fi.invalid> writes:
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.
Jan 18 2007
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"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.
Jan 18 2007
parent =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
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.
Jan 18 2007
prev sibling parent novice <sorry noem.ail> writes:
== 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.
Jan 18 2007
prev sibling parent reply %u <u infearof.spm> writes:
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); ...
Jan 18 2007
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"%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).
Jan 18 2007