www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Problem derrivering nested in child class from nested in parent.

reply Dawid =?ISO-8859-2?Q?Ci=EA=BFarkiewicz?= <arael fov.pl> writes:
class B{
  class InB{
  }
}

class C:B{
  class InC : B.InB{
  }
}

dmd: class d.C.InC super class InB is nested within B, not C

Where is the problem:
a) in notation;
b) in dmd implementation (this feature isn't implemented yet);
c) in my mind (i'm tring to do something ridiculus)?

What am I tring to achive:
InB and InD are both "class Error", B is "class Task" and C is "class
SpecialTask". I throw them when something went wrong in C/B. In their
constructors I call some cleanup functions on C/B. The InB uses:
char[] B.id();
to [prepare msg / log something to output] .
-- 
Dawid Ciężarkiewicz | arael
Jun 26 2005
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Dawid Ciężarkiewicz" <arael fov.pl> wrote in message 
news:d9nchv$g85$1 digitaldaemon.com...
 class B{
  class InB{
  }
 }

 class C:B{
  class InC : B.InB{
  }
 }

I asked if this could be implemented when 0.126 came out. To which Walter replied: "AIEEEE" So, in short, I doubt it'll be implemented. :)
Jun 26 2005
parent reply Dawid =?ISO-8859-2?Q?Ci=EA=BFarkiewicz?= <arael fov.pl> writes:
Jarrett Billingsley wrote:
 "Dawid Ciężarkiewicz" <arael fov.pl> wrote in message
 news:d9nchv$g85$1 digitaldaemon.com...
 class B{
  class InB{
  }
 }

 class C:B{
  class InC : B.InB{
  }
 }

I asked if this could be implemented when 0.126 came out. To which Walter replied: "AIEEEE" So, in short, I doubt it'll be implemented. :)

LOL. I remeber this message. Can we let Walter forget about this neat language feature? Of course no. :D There may be some more important things right now, but "AIEEEE" sounds like "oh god, more to work to do, but it defintly should be done". Right? :D -- Dawid Ciężarkiewicz | arael
Jun 27 2005
next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 27 Jun 2005 10:28:08 +0200, Dawid Ciężarkiewicz <arael fov.pl>  
wrote:
 Jarrett Billingsley wrote:
 "Dawid Ciężarkiewicz" <arael fov.pl> wrote in message
 news:d9nchv$g85$1 digitaldaemon.com...
 class B{
  class InB{
  }
 }

 class C:B{
  class InC : B.InB{
  }
 }

I asked if this could be implemented when 0.126 came out. To which Walter replied: "AIEEEE" So, in short, I doubt it'll be implemented. :)

LOL. I remeber this message. Can we let Walter forget about this neat language feature? Of course no. :D There may be some more important things right now, but "AIEEEE" sounds like "oh god, more to work to do, but it defintly should be done". Right? :D

Depends. Why have the Error classes within the other ones? Regan
Jun 27 2005
parent reply Dawid =?ISO-8859-2?Q?Ci=EA=BFarkiewicz?= <arael fov.pl> writes:
Regan Heath wrote:
 Depends. Why have the Error classes within the other ones?

I'm not sure if I understand the question. I keep the Error classes inside because they are (conceptionaly) part of outside class. And it's saves the global namespace. This way I can catch Parser.Error rather than ParserError. If Error classes are nested I can do some cleanup easly when throwing such Error (in Parser.Error.this()) and I'm sure I won't lost the track of Parser object (nested class store hidden pointer to outside class - that makes me sure I can do real cleanup and garbage collector will not delete my Parser object as long I will be handling exception). Of course I can declare Parse.Error as static (I'm doing so because of that problem with inheritance in nested classess) and pass Parse.this manually - but aren't nested class created to do this for me? I strongly agree with "Keep It Simple" directive. But wouldn't be that rather simple addition to language? As I understand nested classess are just normal static nested classess with hidden pointer to outer class. Nothing changes when allowing such inheritance, right? Still there is a pointer, still is it inited with outher class this, still he behaves as normal D's pointer (reference) to class. Or am I missing something? (it's very possible :) ) If this is realy big problem - as I said - I can "hack" this behavior already without much problem. But if not - it would be neat to have it in D. Thanks, -- Dawid Ciężarkiewicz | arael
Jun 27 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 27 Jun 2005 23:45:36 +0200, Dawid Ciężarkiewicz <arael fov.pl>  
wrote:
 Regan Heath wrote:
 Depends. Why have the Error classes within the other ones?

I'm not sure if I understand the question. I keep the Error classes inside because they are (conceptionaly) part of outside class. And it's saves the global namespace. This way I can catch Parser.Error rather than ParserError. If Error classes are nested I can do some cleanup easly when throwing such Error (in Parser.Error.this()) and I'm sure I won't lost the track of Parser object (nested class store hidden pointer to outside class - that makes me sure I can do real cleanup and garbage collector will not delete my Parser object as long I will be handling exception). Of course I can declare Parse.Error as static (I'm doing so because of that problem with inheritance in nested classess) and pass Parse.this manually - but aren't nested class created to do this for me?

It seems to me that: - ParseError would not pollute the global namespace (in any detrimental way I can see). - ParseError is a name which suggests something conceptually part of something called "Parse". You're dead right about nested classes though. However, I'm not sure I understand the need in the case of error classes. An exception/error should contain all the information it requires, I assume you're saying that is the _whole_ main class? thus why you want the nested class? Surely you don't need it all, but just some part of it? In which case it error class doesn't need to be nested.
 I strongly agree with "Keep It Simple" directive. But wouldn't be that
 rather simple addition to language?

Who knows.. Walters response seemed to indicate that it looked bad (at least at first).
 As I understand nested classess are
 just normal static nested classess with hidden pointer to outer class.
 Nothing changes when allowing such inheritance, right? Still there is a
 pointer, still is it inited with outher class this, still he behaves as
 normal D's pointer (reference) to class.

 Or am I missing something? (it's very possible :) ) If this is realy big
 problem - as I said - I can "hack" this behavior already without much
 problem. But if not - it would be neat to have it in D.

Yeah, I can understand the desire. I think we'll have to wait for Walter to comment on this one. Regan
Jun 27 2005
parent reply Dawid =?ISO-8859-2?Q?Ci=EA=BFarkiewicz?= <arael fov.pl> writes:
Regan Heath wrote:
 It seems to me that:
 - ParseError would not pollute the global namespace (in any detrimental
 way I can see).

class ParserError : Error{ .... } class Parser{ ... } vs. class Parser{ class Error : object.Error{ ... } ... } Second is cleaner IMO. Only one class in global namespace declared, shorther (and more readable) names.
 - ParseError is a name which suggests something conceptually part of
 something called "Parse".

Yes. Error generated by Parser is in some way part of Parser class (not object). But the main reason is naming - I just like Parser.Error better.
 However, I'm not sure I understand the need in the case of error classes.
 An exception/error should contain all the information it requires, I
 assume you're saying that is the _whole_ main class? thus why you want the
 nested class?

The reasons are: - I can't say what I will be doing with such an Parser.Error. Maybe I would like to print debug message containing for example "Parser id", "Parser last token" etc. Having whole Parser will let me to add such things easly in future. It's cheap in a matter of memory - only one additional pointer, rather than coping all necessary informations. - Parser returning Error (unrecovable) should be unregister from owning objects and cleaned possibly fast (precious resources :) ). I can make it using Parser.Error constructor and such Parser will not be deleted by GC because of this hidden pointer inside nested class. Right after Parser.Error is handled and forgoten GC will take care of freeing memory used by Parser.Error and Parser instances.
 Surely you don't need it all, but just some part of it? In which case it
 error class doesn't need to be nested.

Yes. I can have naming like this without nested class (using static nested class). I just change: class Parser{ class Error : object.Error{ this(){ .. } ... } ... } into: class Parser{ static class Error : object.Error{ Parser mParser; this(Parser p){ mParser = p .. } ... } ... } and even worst inheritance will work right now. What am I loosing is: - convenience - I need to manually take care of "p" reference; Yes, I know - it's /only/ convenience. But ... :) -- Dawid Ciężarkiewicz | arael
Jun 27 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 28 Jun 2005 01:58:30 +0200, Dawid Ciężarkiewicz <arael fov.pl>  
wrote:
 Regan Heath wrote:
 It seems to me that:
 - ParseError would not pollute the global namespace (in any detrimental
 way I can see).

class ParserError : Error{ .... } class Parser{ ... } vs. class Parser{ class Error : object.Error{ ... } ... } Second is cleaner IMO. Only one class in global namespace declared, shorther (and more readable) names.

Where is the detrimental effect? The chance of a name collision i.e. someone else with a class called ParserError is slight, it increases only if you name your classes badly (Parser/ParserError is perhaps an example of that, though I imagine it is imported privately into a file defining a parser specialisation and error specialisation eg FooParser/FooParserError).
 - ParseError is a name which suggests something conceptually part of
 something called "Parse".

Yes. Error generated by Parser is in some way part of Parser class (not object). But the main reason is naming - I just like Parser.Error better.

It's aesthetic preference then.
 However, I'm not sure I understand the need in the case of error  
 classes.
 An exception/error should contain all the information it requires, I
 assume you're saying that is the _whole_ main class? thus why you want  
 the
 nested class?

The reasons are: - I can't say what I will be doing with such an Parser.Error. Maybe I would like to print debug message containing for example "Parser id", "Parser last token" etc. Having whole Parser will let me to add such things easly in future.

It may be slightly easier perhaps, but it's not hard to add them to the error class itself.
 It's cheap in a matter of memory - only one additional pointer,
 rather than coping all necessary informations.

Sure. Except that when an exception is thrown the stack unwinds and your Parser reference goes out of scope, this the Gc could collect it before you handle your error, resulting in less memory used, not more.
 - Parser returning Error (unrecovable) should be unregister from owning
 objects and cleaned possibly fast (precious resources :) ).

Yep, all the more reason not to keep a reference to it in the error class.
 I can make it
 using Parser.Error constructor and such Parser will not be deleted by GC
 because of this hidden pointer inside nested class.

Correct, holding onto possbily useless resources, using more memory.
 Right after
 Parser.Error is handled and forgoten GC will take care of freeing memory
 used by Parser.Error and  Parser instances.

Sure, but you only need Parser to hang round cos you haven't yet copied/referenced the debug/error information you need from it. You don't need it to hang round if you've already copied it.
 Surely you don't need it all, but just some part of it? In which case it
 error class doesn't need to be nested.

Yes. I can have naming like this without nested class (using static nested class).

So, the main reason you've nested it is aesthetic? You don't really need/want the outer this pointer in the error class? Regan
Jun 27 2005
next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Regan Heath" <regan netwin.co.nz> wrote in message 
news:opss14krjt23k2f5 nrage.netwin.co.nz...
 So, the main reason you've nested it is aesthetic? You don't really 
 need/want the outer this pointer in the error class?

Maybe he wants namespaces. ;) I'll just keep plugging it... maybe.. someday...
Jun 27 2005
prev sibling parent reply Dawid =?ISO-8859-2?Q?Ci=EA=BFarkiewicz?= <arael fov.pl> writes:
Regan Heath wrote:
 The chance of a name collision i.e. someone else with a class called
 ParserError is slight, it increases only if you name your classes badly
 (Parser/ParserError is perhaps an example of that, though I imagine it is
 imported privately into a file defining a parser specialisation and error
 specialisation eg FooParser/FooParserError).
 
 - ParseError is a name which suggests something conceptually part of
 something called "Parse".

Yes. Error generated by Parser is in some way part of Parser class (not object). But the main reason is naming - I just like Parser.Error better.

It's aesthetic preference then.

Yes. Mostly. I do not expect so many ParserErrors out there.
 However, I'm not sure I understand the need in the case of error
 classes.
 An exception/error should contain all the information it requires, I
 assume you're saying that is the _whole_ main class? thus why you want
 the
 nested class?

The reasons are: - I can't say what I will be doing with such an Parser.Error. Maybe I would like to print debug message containing for example "Parser id", "Parser last token" etc. Having whole Parser will let me to add such things easly in future.

It may be slightly easier perhaps, but it's not hard to add them to the error class itself.

Yes. And everything is about this "slightly easier" words.
 It's cheap in a matter of memory - only one additional pointer,
 rather than coping all necessary informations.

Sure. Except that when an exception is thrown the stack unwinds and your Parser reference goes out of scope, this the Gc could collect it before you handle your error, resulting in less memory used, not more.

Yes. But then I lost whole Parser object that I wish to use somewhere (when I catch Parser.Error). I wan't to free as much resources as I can, but no more. Parser destructor will handle rest right after handling exception.
 I can make it
 using Parser.Error constructor and such Parser will not be deleted by GC
 because of this hidden pointer inside nested class.

Correct, holding onto possbily useless resources, using more memory.
 Right after
 Parser.Error is handled and forgoten GC will take care of freeing memory
 used by Parser.Error and  Parser instances.

Sure, but you only need Parser to hang round cos you haven't yet copied/referenced the debug/error information you need from it. You don't need it to hang round if you've already copied it.

Sometime cost of coping needed information would be much larger than just using already allocated memory. The whole point isn't about memory and resources. I've said about unregistering just to give an example of functionality. The reason why I need it nested is because I don't want to free this "broken" Parser instance right now, but right after handling exception. I can find many reasons why I would like such a behaviour: - maybe exception handler would like to store somewhere this broken parser; - maybe ex. h. know how to "fix" this Parser instance and reuse it; - maybe ex. h. wan't to log something and I don't know what; it may be little part of whole Parser, but I don't know which one; - they may be many ex. handlers and I can not be sure what else can they do; anyhow I want to let them do as much as I can;
 So, the main reason you've nested it is aesthetic? You don't really
 need/want the outer this pointer in the error class?

Aesthetic & convenience. The whole diffrence between nested class and static nested class is this hidden pointer. So if I want described behavior I will pass this reference manually. You may disagree with me if such behaviour of Errors/Exceptions is right or not, but someone may find an example (something else than Errors) that you would agree with him. So if nested functions were added to D to pass this reference automagically than we shall use it for our convenience. But current nested classess have somewhat limited (artificialy IMO) functionality. I say artificialy because I think (I may be wrong) just leting described inheritance work wouldn't created any change in other parts of the language. I hope we disagree only about Errors, and not a need of allowing "derrivering nested in child class from nested in parent". Yes - and sorry for my english. :) -- Dawid Ciężarkiewicz | arael
Jun 28 2005
parent "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 28 Jun 2005 12:08:08 +0200, Dawid Ciężarkiewicz <arael fov.pl>  
wrote:
 I hope we disagree only about Errors, and not a need of allowing
 "derrivering nested in child class from nested in parent".

It seems useful. I've not done a lot of programming with nested classes so I can't really say much more. I was mainly interested in the reasoning for making the Error class nested. You seem to have it well thought out and I tend to agree with you, it does seem useful. Thanks.
 Yes - and sorry for my english. :)

Your english is very good. I wish I spoke a second language half as well. Regan
Jun 28 2005
prev sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Dawid Ciężarkiewicz" <arael fov.pl> wrote in message 
news:d9odau$1bc0$1 digitaldaemon.com...
 LOL. I remeber this message. Can we let Walter forget about this neat
 language feature? Of course no. :D There may be some more important things
 right now, but "AIEEEE" sounds like "oh god, more to work to do, but it
 defintly should be done". Right? :D

Maybe. I mean, it would be a cool feature to have, but I can definitely see how complex and confusing it would be for both the compiler and the compiler writer. And part of the "D mantra" is "keep it simple, so there are more correct implementations out there." Though one thing I'd like to see, and don't know why it doesn't work, is this: class A { class InA { } InA ina; } class B : A { InA ina2; } Why can't B have an InA? The error says that the "this" for "ina2" must be an "A," but a B _is_ an A, by the very definition of inheritance.
Jun 27 2005