www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Inheritance problem

reply %u <unknown unknown.com> writes:
Hello,

I've a problem with my class inheritance. I have class called Texture
which implements the interface IDrawable and the abstract class
APickable.
The Texture-class contains 3 members which looks like this:

GLuint pTextureID;

Size pSize1, pSize2;

Finally... my Texture-class looks like:

class Texture : APickable, IDrawable {
   protected {
      GLuint pTextureID;
      Size pSize, pAnoutherSize;
   }
}

now... I have a second class called Animation which looks like this:

class Animation : Texture {
   private {
      Texture[] pFrames;
   }
   public {
      this(string file, string[] paths...) {
         super(file);
         pFrames ~= this;
         foreach(string cur; paths) {
            pFrames ~= new Texture(cur);
         }
      }

      Size getSize() {
         return pFrames[0].pSize;
      }
   }
}

As I know, pFrames[0].pSize can be called... pSize in the Texture-
class is marked as protected, but I get the following error:

Error: class Texture member pSize is not accessible.

When I mark the protected members of the Texture-class as public, it
works (should be clear), but why do I get this error when mark them
as protected?

I hope anyone can help to solve the problem.
Feb 11 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 11 Feb 2011 15:40:18 -0500, %u <unknown unknown.com> wrote:

 Hello,

 I've a problem with my class inheritance. I have class called Texture
 which implements the interface IDrawable and the abstract class
 APickable.
 The Texture-class contains 3 members which looks like this:

 GLuint pTextureID;

 Size pSize1, pSize2;

 Finally... my Texture-class looks like:

 class Texture : APickable, IDrawable {
    protected {
       GLuint pTextureID;
       Size pSize, pAnoutherSize;
    }
 }

 now... I have a second class called Animation which looks like this:

 class Animation : Texture {
    private {
       Texture[] pFrames;
    }
    public {
       this(string file, string[] paths...) {
          super(file);
          pFrames ~= this;
          foreach(string cur; paths) {
             pFrames ~= new Texture(cur);
          }
       }

       Size getSize() {
          return pFrames[0].pSize;
       }
    }
 }

 As I know, pFrames[0].pSize can be called... pSize in the Texture-
 class is marked as protected, but I get the following error:

 Error: class Texture member pSize is not accessible.

 When I mark the protected members of the Texture-class as public, it
 works (should be clear), but why do I get this error when mark them
 as protected?

 I hope anyone can help to solve the problem.
protected means you cannot access it outside the *instance*. The pFrames array references *other instances* of Texture, so they are not accessible. http://www.digitalmars.com/d/2.0/attribute.html#ProtectionAttribute "If accessing a protected instance member through a derived class member function, that member can only be accessed for the object instance which is the ‘this’ object for the member function call." -Steve
Feb 11 2011
parent reply %u <unknown unknown.com> writes:
== Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel
 On Fri, 11 Feb 2011 15:40:18 -0500, %u <unknown unknown.com> wrote:
 Hello,

 I've a problem with my class inheritance. I have class called
Texture
 which implements the interface IDrawable and the abstract class
 APickable.
 The Texture-class contains 3 members which looks like this:

 GLuint pTextureID;

 Size pSize1, pSize2;

 Finally... my Texture-class looks like:

 class Texture : APickable, IDrawable {
    protected {
       GLuint pTextureID;
       Size pSize, pAnoutherSize;
    }
 }

 now... I have a second class called Animation which looks like
this:
 class Animation : Texture {
    private {
       Texture[] pFrames;
    }
    public {
       this(string file, string[] paths...) {
          super(file);
          pFrames ~= this;
          foreach(string cur; paths) {
             pFrames ~= new Texture(cur);
          }
       }

       Size getSize() {
          return pFrames[0].pSize;
       }
    }
 }

 As I know, pFrames[0].pSize can be called... pSize in the Texture-
 class is marked as protected, but I get the following error:

 Error: class Texture member pSize is not accessible.

 When I mark the protected members of the Texture-class as public,
it
 works (should be clear), but why do I get this error when mark
them
 as protected?

 I hope anyone can help to solve the problem.
protected means you cannot access it outside the *instance*. The
pFrames
 array references *other instances* of Texture, so they are not
accessible.
 http://www.digitalmars.com/d/2.0/attribute.html#ProtectionAttribute
 "If accessing a protected instance member through a derived class
member
 function, that member can only be accessed for the object instance
which
 is the ‘this’ object for the member function call."
 -Steve
Thanks, but what about the following: import std.stdio : writeln; class a { public this(int v) { myVar = v; } protected int myVar; } class b : a { private a[] moreInstances; this(int v, int[] vars...) { super(v); moreInstances ~= this; foreach(int cur; vars) { moreInstances ~= new a(cur); } } int getVar() { return moreInstances[1].myVar; } } void main(string[] args) { b exp = new b(0, 1, 2); writeln(exp.getVar()); } This compiles fine and prints the number 1. myVar is also protected in class a, I also call myVar in the getVar()-method of class b.
Feb 11 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 11 Feb 2011 16:14:31 -0500, %u <unknown unknown.com> wrote:

 == Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel
 Thanks, but what about the following:

 import std.stdio : writeln;

 class a  {

 	public this(int v) {
 		myVar = v;
 	}

 	protected int myVar;

 }

 class b : a {

 	private a[] moreInstances;

 	this(int v, int[] vars...) {
 		super(v);
 		moreInstances ~= this;

 		foreach(int cur; vars) {
 			moreInstances ~= new a(cur);
 		}
 	}

 	int getVar() {
 		return moreInstances[1].myVar;
 	}

 }

 void main(string[] args) {
 	b exp = new b(0, 1, 2);
 	writeln(exp.getVar());
 }

 This compiles fine and prints the number 1. myVar is also protected
 in class a, I also call myVar in the getVar()-method of class b.
Any code can access any members defined in the current module, regardless of access attributes (that rule is outlined in the link I sent, I just didn't quote that part). You have to split this into multiple modules to see the other rules take effect. -Steve
Feb 11 2011
next sibling parent %u <unknown unknown.com> writes:
== Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel
 On Fri, 11 Feb 2011 16:14:31 -0500, %u <unknown unknown.com> wrote:
 == Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel

 Thanks, but what about the following:

 import std.stdio : writeln;

 class a  {

 	public this(int v) {
 		myVar = v;
 	}

 	protected int myVar;

 }

 class b : a {

 	private a[] moreInstances;

 	this(int v, int[] vars...) {
 		super(v);
 		moreInstances ~= this;

 		foreach(int cur; vars) {
 			moreInstances ~= new a(cur);
 		}
 	}

 	int getVar() {
 		return moreInstances[1].myVar;
 	}

 }

 void main(string[] args) {
 	b exp = new b(0, 1, 2);
 	writeln(exp.getVar());
 }

 This compiles fine and prints the number 1. myVar is also
protected
 in class a, I also call myVar in the getVar()-method of class b.
Any code can access any members defined in the current module,
regardless
 of access attributes (that rule is outlined in the link I sent, I
just
 didn't quote that part).  You have to split this into multiple
modules to
 see the other rules take effect.
 -Steve
Ah, okay... this means I have to Texture and Animation into one module. Thanks a lot!
Feb 11 2011
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Steven Schveighoffer:

 Any code can access any members defined in the current module, regardless  
 of access attributes
I am not sure if Walter understands how much this rule makes it hard for people not already used to protected/private attributes to understand and learn to use much more strict. I think this makes learning the usage of those attributes faster. Bye, bearophile
Feb 11 2011
next sibling parent %u <unknown unknown.com> writes:
== Auszug aus bearophile (bearophileHUGS lycos.com)'s Artikel
 Steven Schveighoffer:
 Any code can access any members defined in the current module,
regardless
 of access attributes
I am not sure if Walter understands how much this rule makes it
hard for people not already used to protected/private attributes to compiler doesn't have that rule, and it's much more strict. I think this makes learning the usage of those attributes faster.
 Bye,
 bearophile
I already used protected/private (and other languages like Java and... D too), but it was a bit unintelligible because protected means (for me) that every instance of an inheritanced class can access the protected members. An alternative to protected like modprotected or something like this should be added that people can declare it as modprotected which means that inheritanced classes of another module can also access these attributes.
Feb 11 2011
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 2/11/11, bearophile <bearophileHUGS lycos.com> wrote:
 Steven Schveighoffer:

 Any code can access any members defined in the current module, regardless

 of access attributes
I am not sure if Walter understands how much this rule makes it hard for people not already used to protected/private attributes to understand and rule, and it's much more strict. I think this makes learning the usage of those attributes faster. Bye, bearophile
I think one benefit of the current approach is that we'll be able to use free functions which could be called as if they belong to a class (if they have that class as the first parameter), since we could use the uniform function call (UFC) syntax. But UFC doesn't work with classes yet, otherwise we might be able to do this: module foo; import std.stdio; class Foo { private int _x, _y; this(int x, int y) { _x = x; _y = y; } } int sumXY(Foo foo) { return foo._x + foo._y; } module main; import foo; import std.stdio; void main() { auto obj = new Foo(10, 10); writeln(obj.sumXY()); // using UFC, but doesn't work yet //~ writeln(obj._x + obj._y); // not allowed } We could have a bunch of templated functions in the foo module which could work with any class inside that module. So it might help out against the common God class problem. What do you think?
Feb 11 2011
next sibling parent %u <unknown unknown.com> writes:
== Auszug aus Andrej Mitrovic (andrej.mitrovich gmail.com)'s Artikel
 On 2/11/11, bearophile <bearophileHUGS lycos.com> wrote:
 Steven Schveighoffer:

 Any code can access any members defined in the current module,
regardless
 of access attributes
I am not sure if Walter understands how much this rule makes it
hard for
 people not already used to protected/private attributes to
understand and

have that
 rule, and it's much more strict. I think this makes learning the
usage of
 those attributes faster.

 Bye,
 bearophile
I think one benefit of the current approach is that we'll be able to use free functions which could be called as if they belong to a
class
 (if they have that class as the first parameter), since we could use
 the uniform function call (UFC) syntax. But UFC doesn't work with
 classes yet, otherwise we might be able to do this:
 module foo;
 import std.stdio;
 class Foo {
     private int _x, _y;
     this(int x, int y) {
         _x = x;
         _y = y;
     }
 }
 int sumXY(Foo foo) {
     return foo._x + foo._y;
 }
 module main;
 import foo;
 import std.stdio;
 void main() {
     auto obj = new Foo(10, 10);
     writeln(obj.sumXY());  // using UFC, but doesn't work yet
     //~ writeln(obj._x + obj._y);  // not allowed
 }
 We could have a bunch of templated functions in the foo module which
 could work with any class inside that module. So it might help out
 against the common God class problem. What do you think?
Looks really interesting - would be a nice feature :)
Feb 11 2011
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 11 Feb 2011 17:26:29 -0500, Andrej Mitrovic  
<andrej.mitrovich gmail.com> wrote:

 On 2/11/11, bearophile <bearophileHUGS lycos.com> wrote:
 Steven Schveighoffer:

 Any code can access any members defined in the current module,  
 regardless

 of access attributes
I am not sure if Walter understands how much this rule makes it hard for people not already used to protected/private attributes to understand and that rule, and it's much more strict. I think this makes learning the usage of those attributes faster. Bye, bearophile
I think one benefit of the current approach is that we'll be able to use free functions which could be called as if they belong to a class (if they have that class as the first parameter), since we could use the uniform function call (UFC) syntax. But UFC doesn't work with classes yet, otherwise we might be able to do this: module foo; import std.stdio; class Foo { private int _x, _y; this(int x, int y) { _x = x; _y = y; } } int sumXY(Foo foo) { return foo._x + foo._y; } module main; import foo; import std.stdio; void main() { auto obj = new Foo(10, 10); writeln(obj.sumXY()); // using UFC, but doesn't work yet //~ writeln(obj._x + obj._y); // not allowed }
What's wrong with: class Foo { private int _x, _y; this(int x, int y) { _x = x; _y = y; } int sumXY() { return _x + _y; } }
 We could have a bunch of templated functions in the foo module which
 could work with any class inside that module. So it might help out
 against the common God class problem. What do you think?
I'm unaware of this problem, but I'm not sure it's a huge problem. The UFC syntax is a marginal benefit, making a function look like it's part of the class. The "horrible" alternative is to simply call the function with Foo as a parameter instead of the source. i.e. f(x) vs. x.f() Couldn't the same be achieved via mixins? And in fact, the mixin I think can be defined in a separate module, more flexible. -Steve
Feb 14 2011
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 2/14/11, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 What's wrong with:

 class Foo {
      private int _x, _y;
      this(int x, int y) {
          _x = x;
          _y = y;
      }
      int sumXY() {
          return _x + _y;
      }
 }
Nothing! But the OP asked why it's possible to access the private state of a class if the code that accesses it is in the same module as the class. So I just threw in an example (which admittedly doesn't make much sense, and personally I don't like to access private state outside the class).
Feb 14 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 14 Feb 2011 10:52:41 -0500, Andrej Mitrovic  
<andrej.mitrovich gmail.com> wrote:

 On 2/14/11, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 What's wrong with:

 class Foo {
      private int _x, _y;
      this(int x, int y) {
          _x = x;
          _y = y;
      }
      int sumXY() {
          return _x + _y;
      }
 }
Nothing! But the OP asked why it's possible to access the private state of a class if the code that accesses it is in the same module as the class. So I just threw in an example (which admittedly doesn't make much sense, and personally I don't like to access private state outside the class).
I meant as an alternative to UFC syntax. I still am not enamored by it's capabilities. FWIW, classes/functions/structs in the same module are able to access all private and protected data to alleviate the need for the 'friend' attribute in C++. In C++ a friend function is able to access all private data. The most common use of friend functions is for output stream processors (since the operator is on the stream and not the object being outputted). The theory for the private access in a module goes that likely the same author wrote all the code in that module, so he should understand what the code is supposed to do and have free access to anything. It seems to work pretty well in practice (at least for me anyway). -Steve
Feb 14 2011
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 2/14/11, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 In C++ a friend function is able to access all private
 data.  The most common use of friend functions is for output stream
 processors (since the operator is on the stream and not the object being
 outputted).
Oh right, these << << <<? Ugly things. :p
Feb 14 2011
prev sibling parent spir <denis.spir gmail.com> writes:
On 02/14/2011 05:13 PM, Steven Schveighoffer wrote:
 The theory for the private access in a module goes that likely the same author
 wrote all the code in that module, so he should understand what the code is
 supposed to do and have free access to anything.  It seems to work pretty well
 in practice (at least for me anyway).
The same logic applies in languages of the module/oberon line (which have a good reputation afaik for their module system). Encapsulation plays at the module level. Eg in Oberon all is visible inside a module; the difference is exported/public thingies are marked (with '*'), instead of the opposite in D (which is in my view more like a dynamic language on this point). denis -- _________________ vita es estrany spir.wikidot.com
Feb 14 2011
prev sibling parent spir <denis.spir gmail.com> writes:
On 02/11/2011 11:26 PM, Andrej Mitrovic wrote:
 On 2/11/11, bearophile<bearophileHUGS lycos.com>  wrote:
 Steven Schveighoffer:

 Any code can access any members defined in the current module, regardless

 of access attributes
I am not sure if Walter understands how much this rule makes it hard for people not already used to protected/private attributes to understand and rule, and it's much more strict. I think this makes learning the usage of those attributes faster. Bye, bearophile
I think one benefit of the current approach is that we'll be able to use free functions which could be called as if they belong to a class (if they have that class as the first parameter), since we could use the uniform function call (UFC) syntax. But UFC doesn't work with classes yet, otherwise we might be able to do this: module foo; import std.stdio; class Foo { private int _x, _y; this(int x, int y) { _x = x; _y = y; } } int sumXY(Foo foo) { return foo._x + foo._y; } module main; import foo; import std.stdio; void main() { auto obj = new Foo(10, 10); writeln(obj.sumXY()); // using UFC, but doesn't work yet //~ writeln(obj._x + obj._y); // not allowed } We could have a bunch of templated functions in the foo module which could work with any class inside that module. So it might help out against the common God class problem. What do you think?
Interesting. UFC syntax is also criticised (don't remmber on which points exactly), but it brings with nice side-features. Denis -- _________________ vita es estrany spir.wikidot.com
Feb 11 2011