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
next sibling 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
next sibling 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


 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


 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,


 works (should be clear), but why do I get this error when mark


 as protected?

 I hope anyone can help to solve the problem.


 array references *other instances* of Texture, so they are not

 http://www.digitalmars.com/d/2.0/attribute.html#ProtectionAttribute
 "If accessing a protected instance member through a derived class

 function, that member can only be accessed for the object instance

 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
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


 in class a, I also call myVar in the getVar()-method of class b.


 of access attributes (that rule is outlined in the link I sent, I

 didn't quote that part).  You have to split this into multiple

 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 those attributes correctly. The C# 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
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,


 of access attributes


understand and learn to use those attributes correctly. The C# 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 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,



 of access attributes

I am not sure if Walter understands how much this rule makes it


 people not already used to protected/private attributes to


 learn to use those attributes correctly. The C# compiler doesn't


 rule, and it's much more strict. I think this makes learning the


 those attributes faster.

 Bye,
 bearophile

use free functions which could be called as if they belong to a

 (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 next sibling parent "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
prev sibling next sibling parent 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 learn to use those attributes correctly. The C# 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 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
prev sibling next sibling parent "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 learn to use those attributes correctly. The C# 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 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
prev sibling next sibling parent 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
prev sibling next sibling parent "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
prev 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 next 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 learn to use those attributes correctly. The C# 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 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
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