Thread overview
how to change attribute in descendant?
Jan 18, 2007
novice2
Jan 18, 2007
Pragma
Jan 18, 2007
Pragma
Jan 18, 2007
novice
Jan 19, 2007
%u
January 18, 2007
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
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
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
== 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
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
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
"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
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
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
"%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).