digitalmars.D - Class inheritance and string question.
- Marcin (25/25) Jun 09 2004 I haven't experimented much with D yet, but I spotted something that cou...
-
Vathix
(7/18)
Jun 09 2004
"Marcin"
wrote in message - Matthew (8/35) Jun 09 2004 There are lots of those. D does not purport to be a haven solely for dis...
- James Widman (11/13) Jun 09 2004 It probably makes life simpler for the parser to have a special name for...
- Arcane Jill (13/44) Jun 09 2004 I actually really like that way that D does this. I've had some problems...
- Matthew (5/36) Jun 10 2004 Not in the slightest, I'm afraid. If you were allowed to do that, you'd ...
- Arcane Jill (5/35) Jun 10 2004 Check out the strange and rarely used C++ syntax for the constructor B::...
- Matthew (3/38) Jun 10 2004 Of course. But C++ trusts the programmer and Java does not.
- Jan-Eric Duden (9/51) Jun 10 2004 And D trusts the programmer, too. :)
- Marcin (12/15) Jun 10 2004 have a
- Sean Kelly (13/21) Jun 10 2004 Is this even an issue? Why not just do this:
- Marcin (36/58) Jun 10 2004 C++/C#
- Ant (8/16) Jun 10 2004 This is just trying to use an object that wasn't instanciated.
- Sean Kelly (13/30) Jun 10 2004 This is slightly different. If a class has a constructor then it's safe...
- Ant (6/9) Jun 10 2004 [...]
- Sean Kelly (12/40) Jun 10 2004 Certainly. D is a tad different from C++ in that it doesn't require
- Marcin (19/31) Jun 10 2004 isn't
- Arcane Jill (15/30) Jun 10 2004 So don't do it then. It's not compulsory.
- Jan-Eric Duden (20/102) Jun 10 2004 Exactly that type of error can also happen in just normal classes as wel...
- Matthew (3/65) Jun 10 2004 I agree with what you're saying (and I bet Sean does also).
- Matthew (9/30) Jun 10 2004 It should have the same requirement as in C++, that one cannot leave the...
- Sean Kelly (14/21) Jun 10 2004 I would be shocked if this weren't allowed. Some pertinent bits from th...
- Trejkaz Xaoza (28/34) Jun 10 2004 Probably because in Java, you end up with problems like not being able t...
- Sean Kelly (21/52) Jun 11 2004 I would solve your example by having preconditions for super.this(), but...
- Trejkaz Xaoza (15/17) Jun 11 2004 your example by having preconditions for super.this(), but I
- Sean Kelly (8/22) Jun 12 2004 I had meant the in/out blocks. Verifying pre and postconditions is what...
- Sam McCall (17/19) Jun 13 2004 Which is silly, because you can just do this, if the superclass takes at...
- Trejkaz Xaoza (16/35) Jun 13 2004 Naturally. That code works in D because it doesn't have the restriction...
- Sam McCall (10/23) Jun 13 2004 Oops. I thought that code _would_ work with java, having used something
I haven't experimented much with D yet, but I spotted something that could be considered an anomaly to a C++ programmer. Inside the ctor of a derived class you can call to super to initialize the base portion (this is done with initializer lists in C++, before the constructor is entered to signify that base parts are always initialized first, which makes total sense), but the call to super can be placed anywhere inside the constructor. That means you get to play around with the derived object before the base parts are set up, which can cause hell if contained member objects try to use the base portions. Why isn't this dealt with like in Java, where the call to super has to be the first call in the constructor, otherwise the default base ctor is called. An unrelated question is why does D insist on calling a constructor "this()" unlike most (all?) other OOP languages? Seems like name pollution to me, and the keyword this is already reserved for the this reference. Lastly, I've observed that strings can be initialized like this: char[] str = null; That looks very backwards because it allows for code like this: char[] str = null; if (str == "") printf("whatever"); a null reference means there's no string object at all. Yet it (the phantom string) compares equal to an empty string. Totally unituitive and doesn't look too well thought out. There's a big discussion about this here: http://www.osnews.com/comment.php?news_id=6761&offset=30&rows=45 (search for posts by Marcus, Owen, J.F., ignore the rest)
Jun 09 2004
"Marcin" <sixpackguy earthlink.net> wrote in message news:ca8hdu$1jnl$1 digitaldaemon.com... ...Lastly, I've observed that strings can be initialized like this: char[] str = null; That looks very backwards because it allows for code like this: char[] str = null; if (str == "") printf("whatever"); a null reference means there's no string object at all. Yet it (thephantomstring) compares equal to an empty string. Totally unituitive and doesn't look too well thought out. There's a big discussion about this here: http://www.osnews.com/comment.php?news_id=6761&offset=30&rows=45 (searchforposts by Marcus, Owen, J.F., ignore the rest)null is a special case char[] that means address 0 and length 0. When you compare its value with "", they are equal, like: memcmp("", NULL, 0);
Jun 09 2004
"Marcin" <sixpackguy earthlink.net> wrote in message news:ca8hdu$1jnl$1 digitaldaemon.com...I haven't experimented much with D yet, but I spotted something that could be considered an anomaly to a C++ programmer.There are lots of those. D does not purport to be a haven solely for disenchanted C++ programmers. It offers many things to many viewpoints.Inside the ctor of a derived class you can call to super to initialize the base portion (this is done with initializer lists in C++, before the constructor is entered to signify that base parts are always initialized first, which makes total sense), but the call to super can be placed anywhere inside the constructor. That means you get to play around with the derived object before the base parts are set up, which can cause hell if contained member objects try to use the base portions. Why isn't this dealt with like in Java, where the call to super has to be the first call in the constructor, otherwise the default base ctor is called.This is an important point.An unrelated question is why does D insist on calling a constructor "this()" unlike most (all?) other OOP languages? Seems like name pollution to me, and the keyword this is already reserved for the this reference.This is a pretty trivial issue, don't you think?Lastly, I've observed that strings can be initialized like this: char[] str = null; That looks very backwards because it allows for code like this: char[] str = null; if (str == "") printf("whatever"); a null reference means there's no string object at all. Yet it (the phantom string) compares equal to an empty string. Totally unituitive and doesn't look too well thought out.I think when you get used to it you'll see that it's anything but. It's actually extremenly convenient.There's a big discussion about this here: http://www.osnews.com/comment.php?news_id=6761&offset=30&rows=45 (search for posts by Marcus, Owen, J.F., ignore the rest)
Jun 09 2004
In article <ca8hdu$1jnl$1 digitaldaemon.com>, "Marcin" <sixpackguy earthlink.net> wrote:An unrelated question is why does D insist on calling a constructor "this()" unlike most (all?) other OOP languages?It probably makes life simpler for the parser to have a special name for special functions like that. At any rate, it's simpler than C++, where ctors don't really have names (seeISO C++2003 12.1). Also, special names for ctors are not unheard of in other OO languages. See Python and Ruby for examples. Using 'this' as that special name shouldn't lead us down the path of extreme ambiguity. this() is a ctor, this is the literal "this", and this.this is probably the ctor. :-) James
Jun 09 2004
In article <ca8hdu$1jnl$1 digitaldaemon.com>, Marcin says...I haven't experimented much with D yet, but I spotted something that could be considered an anomaly to a C++ programmer. Inside the ctor of a derived class you can call to super to initialize the base portion (this is done with initializer lists in C++, before the constructor is entered to signify that base parts are always initialized first, which makes total sense), but the call to super can be placed anywhere inside the constructor. That means you get to play around with the derived object before the base parts are set up, which can cause hell if contained member objects try to use the base portions. Why isn't this dealt with like in Java, where the call to super has to be the first call in the constructor, otherwise the default base ctor is called.I actually really like that way that D does this. I've had some problems with both C++ and Java. I can't remember the details, but I think it was something like:MyClass() // Java constructor - D would use this() { try { super(); /* the rest */ } catch (Exception e) { /* do something else */ } }I may have got the details wrong, but it was something like that. Anyway, Java freaked out because super() wasn't the first thing in the constructor - but you can clearly see it makes perfect sense. Similar problems arise (in Java) if you try to replace try { ... } with synchronized(SomeObject) { ... }. Another situation is:this(MyEnum e) { switch(e) { case MyEnum.CASE1: super(parameters for case 1); break; case MyEnum.CASE2: super(parameters for case 2); break; case MyEnum.CASE3: super(parameters for case 3); break; ...etc.No, on the whole, I think D has got it right. If you want super() called first, then call it first, or don't explicitly call it at all. But there will always be the odd special case where you really need to do something differently. Arcane Jill
Jun 09 2004
"Arcane Jill" <Arcane_member pathlink.com> wrote in message news:ca8vto$2ahj$1 digitaldaemon.com...In article <ca8hdu$1jnl$1 digitaldaemon.com>, Marcin says...Not in the slightest, I'm afraid. If you were allowed to do that, you'd have a "validly" constructed MyClass instance whose base class portion was undefined. Very bad.I haven't experimented much with D yet, but I spotted something that could be considered an anomaly to a C++ programmer. Inside the ctor of a derived class you can call to super to initialize the base portion (this is done with initializer lists in C++, before the constructor is entered to signify that base parts are always initialized first, which makes total sense), but the call to super can be placed anywhere inside the constructor. That means you get to play around with the derived object before the base parts are set up, which can cause hell if contained member objects try to use the base portions. Why isn't this dealt with like in Java, where the call to super has to be the first call in the constructor, otherwise the default base ctor is called.I actually really like that way that D does this. I've had some problems with both C++ and Java. I can't remember the details, but I think it was something like:MyClass() // Java constructor - D would use this() { try { super(); /* the rest */ } catch (Exception e) { /* do something else */ } }I may have got the details wrong, but it was something like that. Anyway, Java freaked out because super() wasn't the first thing in the constructor - but you can clearly see it makes perfect sense.
Jun 10 2004
In article <ca9286$2fe1$1 digitaldaemon.com>, Matthew says...Not in the slightest, I'm afraid. If you were allowed to do that, you'd have a "validly" constructed MyClass instance whose base class portion was undefined. Very bad.Well, of course, you can do that in C++. This compiles fine using gcc:class A { public : A(void); }; A::A(void) { } class B : public A { public : B(void); }; // This is the interesting bit B::B(void) try : A() { } catch (...) { } int main(void) { }Check out the strange and rarely used C++ syntax for the constructor B::B. It will catch exceptions which are thrown in the base class. Arcane Jill
Jun 10 2004
"Arcane Jill" <Arcane_member pathlink.com> wrote in message news:ca94m4$2ius$1 digitaldaemon.com...In article <ca9286$2fe1$1 digitaldaemon.com>, Matthew says...Of course. But C++ trusts the programmer and Java does not.Not in the slightest, I'm afraid. If you were allowed to do that, you'd have a "validly" constructed MyClass instance whose base class portion was undefined. Very bad.Well, of course, you can do that in C++. This compiles fine using gcc:class A { public : A(void); }; A::A(void) { } class B : public A { public : B(void); }; // This is the interesting bit B::B(void) try : A() { } catch (...) { } int main(void) { }Check out the strange and rarely used C++ syntax for the constructor B::B. It will catch exceptions which are thrown in the base class.
Jun 10 2004
And D trusts the programmer, too. :) And I like that. -- Jan-Eric Duden "Matthew" <matthew.hat stlsoft.dot.org> wrote in message news:ca96fo$2lbm$1 digitaldaemon.com..."Arcane Jill" <Arcane_member pathlink.com> wrote in message news:ca94m4$2ius$1 digitaldaemon.com...have aIn article <ca9286$2fe1$1 digitaldaemon.com>, Matthew says...Not in the slightest, I'm afraid. If you were allowed to do that, you'dundefined."validly" constructed MyClass instance whose base class portion wasB::B. ItVery bad.Well, of course, you can do that in C++. This compiles fine using gcc:class A { public : A(void); }; A::A(void) { } class B : public A { public : B(void); }; // This is the interesting bit B::B(void) try : A() { } catch (...) { } int main(void) { }Check out the strange and rarely used C++ syntax for the constructorwill catch exceptions which are thrown in the base class.Of course. But C++ trusts the programmer and Java does not.
Jun 10 2004
"Matthew" <matthew.hat stlsoft.dot.org> wrote in message news:ca9286$2fe1$1 digitaldaemon.com...Not in the slightest, I'm afraid. If you were allowed to do that, you'dhave a"validly" constructed MyClass instance whose base class portion wasundefined.Very bad.syntax because it lets you catch base class exceptions and then translate and rethrow. With D you have to be careful about your member objects not to call any base portions or it will be undefined, and you have to be careful not to call any methods/functions that will use base poritions or the result will be undefined. Wouldn't it be much better and logical if base class portions were guaranteed to have finished before you can write a single line of code in the derived ctor?
Jun 10 2004
In article <caa5q6$1844$1 digitaldaemon.com>, Marcin says...syntax because it lets you catch base class exceptions and then translate and rethrow. With D you have to be careful about your member objects not to call any base portions or it will be undefined, and you have to be careful not to call any methods/functions that will use base poritions or the result will be undefined. Wouldn't it be much better and logical if base class portions were guaranteed to have finished before you can write a single line of code in the derived ctor?Is this even an issue? Why not just do this: class A {} class B { this() { try { super(); } catch( Exception e ) { throw new DerivedException(); } } } It seems far cleaner than the function try blocks in C++. Sean
Jun 10 2004
"Sean Kelly" <sean f4.ca> wrote in message news:caa790$1adj$1 digitaldaemon.com...In article <caa5q6$1844$1 digitaldaemon.com>, Marcin says...tosyntax because it lets you catch base class exceptions and then translate and rethrow. With D you have to be careful about your member objects notcarefulcall any base portions or it will be undefined, and you have to beresultnot to call any methods/functions that will use base poritions or thelinewill be undefined. Wouldn't it be much better and logical if base class portions were guaranteed to have finished before you can write a singleYou're missing the big picture. I'm not arguing over which syntax is better. Take a look at this: class base { private: int x; public: void print() { printf("%d\n", x); } this() { x = 8; printf("constructing base\n"); } } class derived : base { this() { print(); super(); } } When you construct a derived object, you're accessing a function (print) in an object that doesn't exist yet - base. If this isn't a recipe for disaster then I don't know what is. This must not ever happen. You should really read this: http://www.gotw.ca/gotw/066.htm .of code in the derived ctor?Is this even an issue? Why not just do this: class A {} class B { this() { try { super(); } catch( Exception e ) { throw new DerivedException(); } } } It seems far cleaner than the function try blocks in C++. Sean
Jun 10 2004
In article <caadke$1jmk$1 digitaldaemon.com>, Marcin says...class derived : base { this() { print(); super(); } }This is just trying to use an object that wasn't instanciated. It's the same as: base b; b.print(); (javac for example will issue an error) I don't see a big problem with it. Ant
Jun 10 2004
In article <caaed0$1km1$1 digitaldaemon.com>, Ant says...In article <caadke$1jmk$1 digitaldaemon.com>, Marcin says...This is slightly different. If a class has a constructor then it's safe to assume that something inside that class requires initialization in order to work properly. Assuming the class only contains standard D class references and such then the worst that will happen is the runtime error you've mentioned. But assume for a moment that the class uses pointers, special memory allocators, and all sorts of other weirdness. In that case the program may crash horribly if a function is called on the class before it is properly initialized. So in general terms: "the result of calling a function on an unconstructed class instance is undefined." Usually this means the app will crash but it can also lead to either subtle bugs or crazy stuff like your hard drive being erased. Slightly different from trying to access a null reference :) Seanclass derived : base { this() { print(); super(); } }This is just trying to use an object that wasn't instanciated. It's the same as: base b; b.print(); (javac for example will issue an error) I don't see a big problem with it.
Jun 10 2004
In article <caaevs$1llt$1 digitaldaemon.com>, Sean Kelly says...This is slightly different.[...]assume for a moment that the class uses pointers, special memory allocators, and all sorts of other weirdness.[...] I see, thanks. But I still like this feature, I believe I use it somewhere. Ant
Jun 10 2004
In article <caadke$1jmk$1 digitaldaemon.com>, Marcin says...You're missing the big picture. I'm not arguing over which syntax is better. Take a look at this: class base { private: int x; public: void print() { printf("%d\n", x); } this() { x = 8; printf("constructing base\n"); } } class derived : base { this() { print(); super(); } } When you construct a derived object, you're accessing a function (print) in an object that doesn't exist yet - base. If this isn't a recipe for disaster then I don't know what is. This must not ever happen.Certainly. D is a tad different from C++ in that it doesn't require superclasses to be initialized first. This is fine so long as the user isn't foolish enough to try your example above :) And I should point out this quote from the D docs: "If no call to constructors via this or super appear in a constructor, and the base class has a constructor, a call to super() is inserted at the beginning of the constructor." So assuming the user isn't deliberately foolish then everything will work out fine. There's really no reason to explicitly call a superclass constructor with no parameters unless you want to catch any exceptions it throws. Sean
Jun 10 2004
"Sean Kelly" <sean f4.ca> wrote in message news:caaekv$1l7h$1 digitaldaemon.com...In article <caadke$1jmk$1 digitaldaemon.com>, Marcin says...Certainly. D is a tad different from C++ in that it doesn't require superclasses to be initialized first. This is fine so long as the userisn'tfoolish enough to try your example above :) And I should point out thisquotefrom the D docs: "If no call to constructors via this or super appear in a constructor, andthebase class has a constructor, a call to super() is inserted at thebeginning ofthe constructor." So assuming the user isn't deliberately foolish then everything will workoutfine. There's really no reason to explicitly call a superclassconstructor withno parameters unless you want to catch any exceptions it throws. SeanThe example was contrived on purpose so that you can see my point. A lot of times you write code and unknowingly it pretty much does what I just showed you, except now you will be chasing an extremely obscure bug. It's like programming in C, you always want your programs leak and bug free and you never intend to write such programs, but they still happen more often that you'd like to admit to. Having the language help you out is priceless. D doesn't do that and therefore it invites a whole host of bugs. Secondly, why would you not want base class portions initialized first? Would you not start constructing any building with the foundations? All other mature languages guarantee base parts are set up first because it just makes sense from a design standpoint.
Jun 10 2004
In article <caadke$1jmk$1 digitaldaemon.com>, Marcin says...When you construct a derived object, you're accessing a function (print) in an object that doesn't exist yet - base. If this isn't a recipe for disaster then I don't know what is.So don't do it then. It's not compulsory. Look, you can reason by similar argument that a constructor should not be allowed to call any member function of its own class, because, by definition, if the constructor hasn't returned yet, the object isn't fully constructed yet. Look see:class A { this() { print(); printf("finished constructing A\n"); } void print() { printf("executing A.print()\n"); } }We can all write dumb code. The trick is, not to. As things stand, D constructors are nice and readable, and if you do something dumb you can expect your program to fall over. And that's how it should be. Compile-time error checking is there to catch the kinds of errors which are NOT obvious. C++ gives you a tortured syntax which make it much harder to figure out construction order. In D you can just SEE it. So I'm not convinced that either the Java way or the C++ way is better. I still think that D has got the better balance between readability and safety, without compromising what you can do. Arcane Jill
Jun 10 2004
Marcin wrote:"Sean Kelly" <sean f4.ca> wrote in message news:caa790$1adj$1 digitaldaemon.com...Exactly that type of error can also happen in just normal classes as well. class A { int b; this() { print(); b=1; } void print() { assert(b==1); } } Thus I don't see a problem, with the way D does it with super and derived classes. It actually allows the programmer to do stuff without writing create/inits methods as they are needed in C++. For me this issue is really a no brainer.In article <caa5q6$1844$1 digitaldaemon.com>, Marcin says...tosyntax because it lets you catch base class exceptions and then translate and rethrow. With D you have to be careful about your member objects notcarefulcall any base portions or it will be undefined, and you have to beresultnot to call any methods/functions that will use base poritions or thelinewill be undefined. Wouldn't it be much better and logical if base class portions were guaranteed to have finished before you can write a singleYou're missing the big picture. I'm not arguing over which syntax is better. Take a look at this: class base { private: int x; public: void print() { printf("%d\n", x); } this() { x = 8; printf("constructing base\n"); } } class derived : base { this() { print(); super(); } } When you construct a derived object, you're accessing a function (print) in an object that doesn't exist yet - base. If this isn't a recipe for disaster then I don't know what is. This must not ever happen. You should really read this: http://www.gotw.ca/gotw/066.htm .of code in the derived ctor?Is this even an issue? Why not just do this: class A {} class B { this() { try { super(); } catch( Exception e ) { throw new DerivedException(); } } } It seems far cleaner than the function try blocks in C++. Sean
Jun 10 2004
"Marcin" <sixpackguy earthlink.net> wrote in message news:caadke$1jmk$1 digitaldaemon.com..."Sean Kelly" <sean f4.ca> wrote in message news:caa790$1adj$1 digitaldaemon.com...I agree with what you're saying (and I bet Sean does also).In article <caa5q6$1844$1 digitaldaemon.com>, Marcin says...tosyntax because it lets you catch base class exceptions and then translate and rethrow. With D you have to be careful about your member objects notcarefulcall any base portions or it will be undefined, and you have to beresultnot to call any methods/functions that will use base poritions or thelinewill be undefined. Wouldn't it be much better and logical if base class portions were guaranteed to have finished before you can write a singleYou're missing the big picture. I'm not arguing over which syntax is better. Take a look at this: class base { private: int x; public: void print() { printf("%d\n", x); } this() { x = 8; printf("constructing base\n"); } } class derived : base { this() { print(); super(); } }of code in the derived ctor?Is this even an issue? Why not just do this: class A {} class B { this() { try { super(); } catch( Exception e ) { throw new DerivedException(); } } } It seems far cleaner than the function try blocks in C++. Sean
Jun 10 2004
"Sean Kelly" <sean f4.ca> wrote in message news:caa790$1adj$1 digitaldaemon.com...In article <caa5q6$1844$1 digitaldaemon.com>, Marcin says...It should have the same requirement as in C++, that one cannot leave the ctor body (once an x has been caught) via a return statement, but should require the coder to write a throw expression (even if it's only "throw;") One thing I find important a lot in C++ is the ability to be able to write and call static methods in the initialiser list. I'd like to be able to do the same prior to calling super(), and I imagine that I probably can at the moment in D. Anyone know?syntax because it lets you catch base class exceptions and then translate and rethrow. With D you have to be careful about your member objects not to call any base portions or it will be undefined, and you have to be careful not to call any methods/functions that will use base poritions or the result will be undefined. Wouldn't it be much better and logical if base class portions were guaranteed to have finished before you can write a single line of code in the derived ctor?Is this even an issue? Why not just do this: class A {} class B { this() { try { super(); } catch( Exception e ) { throw new DerivedException(); } } } It seems far cleaner than the function try blocks in C++.
Jun 10 2004
In article <caan2q$22ap$1 digitaldaemon.com>, Matthew says...It should have the same requirement as in C++, that one cannot leave the ctor body (once an x has been caught) via a return statement, but should require the coder to write a throw expression (even if it's only "throw;")I agree completely.One thing I find important a lot in C++ is the ability to be able to write and call static methods in the initialiser list. I'd like to be able to do the same prior to calling super(), and I imagine that I probably can at the moment in D. Anyone know?I would be shocked if this weren't allowed. Some pertinent bits from the spec just to back up my guess: "All member initializations must be determinable by the compiler at compile time, hence there is no order-of-evaluation dependency for member initializations, and it is not possible to read a value that has not been initialized." "static this() is called by the startup code before main() is called. . . A current weakness of the static constructors is that the order in which they are called is not defined." So it looks like dependent singleton types may still have some issues but otherwise all should work as expected. Sean
Jun 10 2004
In article <ca8hdu$1jnl$1 digitaldaemon.com>, Marcin says...the call to super can be placed anywhere inside the constructor. That means you get to play around with the derived object before the base parts are set up, which can cause hell if contained member objects try to use the base portions. Why isn't this dealt with like in Java, where the call to super has to be the first call in the constructor, otherwise the default base ctor is called.Probably because in Java, you end up with problems like not being able to do this (translated to D for the sake of the group): class NamedObject { private char[] name; this(char[] name) { this.name = name; } } class NonNullNamedObject : NamedObject { this(char[] name) { if (name is null) { //...throw some exception... } super(name); } } The workaround in this case is obviously to call super(name) first and then to check the value, but wouldn't it make more sense to check the value first before creating a useless object? I figure statements before the super() should be permitted, but perhaps D could just prohibit non-static methods being called. TX
Jun 10 2004
In article <cabl7p$cm3$1 digitaldaemon.com>, Trejkaz Xaoza says...In article <ca8hdu$1jnl$1 digitaldaemon.com>, Marcin says...I would solve your example by having preconditions for super.this(), but I think that's a flaw in the example rather than the idea itself. Suppose a derived class wants to choose which base class constructor to call depending on calculated data? class Derived : Super { ...this( int x ) ...{ .......switch( calculateSomethingWith( x ) ) .......{ .......case 1: super(); break; .......case 2: super( someValue ); break; .......} ...} } In this case the superclass constructor is neither the first call in the derived constructor nor even the first function/method called in the derived constructor, yet the approach seems perfectly legitimate provided the programmer is careful. Seanthe call to super can be placed anywhere inside the constructor. That means you get to play around with the derived object before the base parts are set up, which can cause hell if contained member objects try to use the base portions. Why isn't this dealt with like in Java, where the call to super has to be the first call in the constructor, otherwise the default base ctor is called.Probably because in Java, you end up with problems like not being able to do this (translated to D for the sake of the group): class NamedObject { private char[] name; this(char[] name) { this.name = name; } } class NonNullNamedObject : NamedObject { this(char[] name) { if (name is null) { //...throw some exception... } super(name); } } The workaround in this case is obviously to call super(name) first and then to check the value, but wouldn't it make more sense to check the value first before creating a useless object?
Jun 11 2004
In article <cacsum$23rb$1 digitaldaemon.com>, Sean Kelly says...I would solveyour example by having preconditions for super.this(), but I thinkthat's aflaw in the example rather than the idea itself. The entire _point_ of checking the value was to check the precondition. Or is there another way? Excluding the in and out blocks, of course, as those are compiled out for release builds, and it's hardly acceptable for your program to work in all cases except the release build. TX
Jun 11 2004
In article <cae121$mon$1 digitaldaemon.com>, Trejkaz Xaoza says...In article <cacsum$23rb$1 digitaldaemon.com>, Sean Kelly says...I had meant the in/out blocks. Verifying pre and postconditions is what DBC is for, and in many cases debug testing is sufficient to insure acceptable program correctness. Critical software, however, may actually ship with the in/out blocks still in place, as program failure is not an option. If you're worried about performance then just make sure that the code in in/out is fairly efficient, or put in Internal and Production version blocks. SeanI would solveyour example by having preconditions for super.this(), but I thinkthat's aflaw in the example rather than the idea itself. The entire _point_ of checking the value was to check the precondition. Or is there another way? Excluding the in and out blocks, of course, as those are compiled out for release builds, and it's hardly acceptable for your program to work in all cases except the release build.
Jun 12 2004
Trejkaz Xaoza wrote:Probably because in Java, you end up with problems like not being able to do this (translated to D for the sake of the group):Which is silly, because you can just do this, if the superclass takes at least one parameter: class NonNullNamedObject : NamedObject { this(char[] name) { super(preconstruct(name)); } char[] preconstruct(char[] name) { if(name is null) { // whatever } return name; } } Just having the compiler add an assert that a superconstructor got called exactly once (only in debug mode of course) sounds like enough to me. Sam
Jun 13 2004
Naturally. That code works in D because it doesn't have the restrictions of Java. Java would have complained about code like that since you're calling a method before the object is instantiated. I guess you can use a static method to avoid that, but then again that example I gave wasn't the exact case which I have encountered anyway, more a simulation. :-) But anyway... since I have a preference towards developing library code as opposed to application code, I like being over-careful with what gets passed in. Having my own code go through debug testing a thousand times doesn't help, if someone linking to my library passes in a bad value (this is also why I don't like to rely on the in/out blocks, since I can't guarantee the application which includes my code will actually compile them in! I guess if the specification said in/out blocks were always put in, it would be a different issue.) Anyway, D's going the right way about it. 'Trust the developer' seems to be its philosophy and allowing the superconstructor call anywhere is adhering to that. TX In article <cahg14$2p7c$1 digitaldaemon.com>, Sam McCall says...Trejkaz Xaoza wrote:Probably because in Java, you end up with problems like not being able to do this (translated to D for the sake of the group):Which is silly, because you can just do this, if the superclass takes at least one parameter: class NonNullNamedObject : NamedObject { this(char[] name) { super(preconstruct(name)); } char[] preconstruct(char[] name) { if(name is null) { // whatever } return name; } } Just having the compiler add an assert that a superconstructor got called exactly once (only in debug mode of course) sounds like enough to me. Sam
Jun 13 2004
Trejkaz Xaoza wrote:Naturally. That code works in D because it doesn't have the restrictions of Java. Java would have complained about code like that since you're calling a method before the object is instantiated. I guess you can use a static method to avoid that, but then again that example I gave wasn't the exact case which I have encountered anyway, more a simulation. :-)Oops. I thought that code _would_ work with java, having used something like it before as a hack, but it was static before, which is a different kettle of fish. Of course it works in D, in D you can put the code before the super() call ;-)Having my own code go through debug testing a thousand times doesn't help, if someone linking to my library passes in a bad value (this is also why I don't like to rely on the in/out blocks, since I can't guarantee the application which includes my code will actually compile them in! I guess if the specification said in/out blocks were always put in, it would be a different issue.) Anyway, D's going the right way about it. 'Trust the developer' seems to be its philosophy and allowing the superconstructor call anywhere is adhering to that.Agreed. Maybe you should trust the developer more too - if they use your library incorrectly, never did a debug build, and released their program complete with resultant bugs then they were a lost cause anyway ;) Sam
Jun 13 2004