how to change attribute in descendant?

Pragma ericanderton at yahoo.removeme.com
Thu Jan 18 07:30:22 PST 2007


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


More information about the Digitalmars-d-learn mailing list