Re: Construct immutable member in derived class
On Thursday, 5 April 2018 at 19:31:39 UTC, Jonathan M Davis wrote: And you can't abstract whether a member variable is marked with immutable or not. That's part of the variable. Declaring an immutable instance of an object would then treat the member variable in immutable for that instance, so it's possible to have an immutable member variable when the member variable is not itself marked with immutable, but class inheritance has nothing to do with controlling which type qualifiers were used on the member variable of a base class. Derived classes override member functions. They don't override member variables or anything about them. They override the behavior of the base class, not the structure. That beats my argumentation. Fully agree with that. For them to do otherwise would become quite problematic if you ever use a derived class through a base class reference. They can add onto the structure of a base class, but the derived class must be usuable via a base class reference, and trying to do something like have the derived class alter the qualifiers on base class member variable simply would not work with that. That sort of thing could only ever work if the base class were just a way to add functionality to a derived class rather than having anything to do with references, and that's simply not how classes work in D. If that's the sort of thing that you want, it would make more sense to add the functionality via composition rather than inheritance. Yeah... little bit of mixing things up in my head, maybe... Did exactly this stuff during the last couple of months. Thanks a lot!
Re: Construct immutable member in derived class
On Thursday, April 05, 2018 13:36:07 Alex via Digitalmars-d-learn wrote: > On Wednesday, 4 April 2018 at 21:49:08 UTC, Timoses wrote: > > "[...] the construction of the base class can be independent > > from the derived one." > > > > Hm, the points 7 and 8 don't clearly state what you wrote. > > Yes :) > > > But it somehow does make sense.. Still I wonder why that is so. > > > > Let's say you have an abstract class with immutable members. > > Why shouldn't derived class constructors be allowed to > > initialize these immutable members? > > My reason is a semantic one, so it's rather how I'm explaining > this to me, then a formal one. > > Let's assume, we abstract away a member from different derived > classes to an abstract class, which cannot be handled by this > abstract class. > Ok, this can happen, so it would be ok, if the base class does > not handle the var. > > But then, we add a qualifier. How can this be? As the abstract > class cannot handle the abstraction, it also can not add any > qualifiers. > As the qualifier is there, then, the base class at least has > knowledge about the immutability. And due this fact, its own > constructor has to handle this variable in some way. > > However, this a minor problem, isn't it? If you argue, that you > can also abstract the immutability qualifier, then, I would say, > that a derived class always has a better knowledge how to handle > its members, and therefore how to call the base class > constructor, as it knows which class it is derived from. > > So, for short: > Either: the immutability belongs to the base class and therefore > it has to manage the var > Or: it doesn't and the derived classes have the knowledge how to > serve their base class. The reality of the matter is that a member variable is a member of the class that it's in and _must_ be handled by that class. If it's not directly initialized in its declaration or initialized in that class' constructor, then it gets a default value. Derived classes have _zero_ control over that. They can mutate a public or protected mutable member of a base class, but that member variable still has to be initialized by the base class, not the derived class. And you can't abstract whether a member variable is marked with immutable or not. That's part of the variable. Declaring an immutable instance of an object would then treat the member variable in immutable for that instance, so it's possible to have an immutable member variable when the member variable is not itself marked with immutable, but class inheritance has nothing to do with controlling which type qualifiers were used on the member variable of a base class. Derived classes override member functions. They don't override member variables or anything about them. They override the behavior of the base class, not the structure. For them to do otherwise would become quite problematic if you ever use a derived class through a base class reference. They can add onto the structure of a base class, but the derived class must be usuable via a base class reference, and trying to do something like have the derived class alter the qualifiers on base class member variable simply would not work with that. That sort of thing could only ever work if the base class were just a way to add functionality to a derived class rather than having anything to do with references, and that's simply not how classes work in D. If that's the sort of thing that you want, it would make more sense to add the functionality via composition rather than inheritance. - Jonathan M Davis
Re: Construct immutable member in derived class
On Wednesday, 4 April 2018 at 22:47:07 UTC, Jonathan M Davis wrote: Because doing that basically makes it impossible to guarantee that the type system isn't violated. Once an immutable variable has been initialized, its value must _never_ change. It must be initalized exactly once, and the compiler doesn't necessarily have any clue what the base class constructors did or didn't do. There's no guarantee that it even has access to the function bodies for the base class when compiling the derived class. So, there is no way for it to safely put off the initialization of any base class members for the derived class to do. - Jonathan M Davis Ah, makes sense. I was looking for a somewhat technical answer. Thanks for that : ).
Re: Construct immutable member in derived class
On Wednesday, 4 April 2018 at 21:49:08 UTC, Timoses wrote: "[...] the construction of the base class can be independent from the derived one." Hm, the points 7 and 8 don't clearly state what you wrote. Yes :) But it somehow does make sense.. Still I wonder why that is so. Let's say you have an abstract class with immutable members. Why shouldn't derived class constructors be allowed to initialize these immutable members? My reason is a semantic one, so it's rather how I'm explaining this to me, then a formal one. Let's assume, we abstract away a member from different derived classes to an abstract class, which cannot be handled by this abstract class. Ok, this can happen, so it would be ok, if the base class does not handle the var. But then, we add a qualifier. How can this be? As the abstract class cannot handle the abstraction, it also can not add any qualifiers. As the qualifier is there, then, the base class at least has knowledge about the immutability. And due this fact, its own constructor has to handle this variable in some way. However, this a minor problem, isn't it? If you argue, that you can also abstract the immutability qualifier, then, I would say, that a derived class always has a better knowledge how to handle its members, and therefore how to call the base class constructor, as it knows which class it is derived from. So, for short: Either: the immutability belongs to the base class and therefore it has to manage the var Or: it doesn't and the derived classes have the knowledge how to serve their base class.
Re: Construct immutable member in derived class
On Wednesday, April 04, 2018 21:46:13 Timoses via Digitalmars-d-learn wrote: > On Wednesday, 4 April 2018 at 18:11:12 UTC, Jonathan M Davis > > That code doesn't compile - at least not with dmd master. It > > gives these two errors: > > > > q.d(5): Error: constructor `q.A.this` missing initializer for > > immutable > > field i > > q.d(12): Error: cannot modify immutable expression this.i > > > > So, it's an error that the base class doesn't initialize the > > immutable member, and it's an error for the derived class to > > try to assign to it. > > I know, should have mentioned it. The question is why, however? > A rule like the above would force all derived classes to > initialize the immutable variable from the base class (if they > were allowed to). > Why aren't they? Because doing that basically makes it impossible to guarantee that the type system isn't violated. Once an immutable variable has been initialized, its value must _never_ change. It must be initalized exactly once, and the compiler doesn't necessarily have any clue what the base class constructors did or didn't do. There's no guarantee that it even has access to the function bodies for the base class when compiling the derived class. So, there is no way for it to safely put off the initialization of any base class members for the derived class to do. - Jonathan M Davis
Re: Construct immutable member in derived class
On Wednesday, 4 April 2018 at 16:16:24 UTC, Alex wrote: Here is something: https://dlang.org/spec/class.html#constructors By the rules 7 and 8 it is suggested, what Simen already said, the construction of the base class can be independent from the derived one. And as such, the immutability has to handled in the constructor, next to the variable... "[...] the construction of the base class can be independent from the derived one." Hm, the points 7 and 8 don't clearly state what you wrote. But it somehow does make sense.. Still I wonder why that is so. Let's say you have an abstract class with immutable members. Why shouldn't derived class constructors be allowed to initialize these immutable members?
Re: Construct immutable member in derived class
On Wednesday, 4 April 2018 at 18:11:12 UTC, Jonathan M Davis wrote: On Wednesday, April 04, 2018 16:05:52 Timoses via ``` class A { immutable int i; this(){} } class B : A { this() { this.i = 3; super(); // <- specifically calling //super constructor afterwards } } void main() { auto b = new B; } ``` That code doesn't compile - at least not with dmd master. It gives these two errors: q.d(5): Error: constructor `q.A.this` missing initializer for immutable field i q.d(12): Error: cannot modify immutable expression this.i So, it's an error that the base class doesn't initialize the immutable member, and it's an error for the derived class to try to assign to it. - Jonathan M Davis I know, should have mentioned it. The question is why, however? A rule like the above would force all derived classes to initialize the immutable variable from the base class (if they were allowed to). Why aren't they?
Re: Construct immutable member in derived class
On Wednesday, April 04, 2018 16:05:52 Timoses via Digitalmars-d-learn wrote: > On Wednesday, 4 April 2018 at 10:41:52 UTC, Simen Kjærås wrote: > > Because by the time B's constructor is called, A might already > > have initialized it, and rely on it never changing. > > What about: > > ``` > class A > { > immutable int i; > > this(){} > } > > class B : A > { > this() > { > this.i = 3; > super(); // <- specifically calling >//super constructor afterwards > } > } > > void main() > { > auto b = new B; > } > ``` That code doesn't compile - at least not with dmd master. It gives these two errors: q.d(5): Error: constructor `q.A.this` missing initializer for immutable field i q.d(12): Error: cannot modify immutable expression this.i So, it's an error that the base class doesn't initialize the immutable member, and it's an error for the derived class to try to assign to it. - Jonathan M Davis
Re: Construct immutable member in derived class
On Wednesday, 4 April 2018 at 16:05:52 UTC, Timoses wrote: This becomes a bit hideous, unfortunately, when there are many initializations involved. Found this, but it doesn't mention anything about derived classes.. https://dlang.org/spec/class.html#field-init Here is something: https://dlang.org/spec/class.html#constructors By the rules 7 and 8 it is suggested, what Simen already said, the construction of the base class can be independent from the derived one. And as such, the immutability has to handled in the constructor, next to the variable...
Re: Construct immutable member in derived class
On Wednesday, 4 April 2018 at 10:41:52 UTC, Simen Kjærås wrote: Because by the time B's constructor is called, A might already have initialized it, and rely on it never changing. What about: ``` class A { immutable int i; this(){} } class B : A { this() { this.i = 3; super(); // <- specifically calling //super constructor afterwards } } void main() { auto b = new B; } ``` Same result The solution is to add a constructor overload to A, and call that from B: class A { immutable int i; protected this(int i) { this.i = i; } } class B : A { this() { super(3); } } unittest { auto b = new B; } -- Simen This becomes a bit hideous, unfortunately, when there are many initializations involved. Found this, but it doesn't mention anything about derived classes.. https://dlang.org/spec/class.html#field-init
Re: Construct immutable member in derived class
On Wednesday, 4 April 2018 at 10:11:37 UTC, Timoses wrote: Example: ``` class A { immutable int i; this(){} } class B : A { this() { this.i = 3; } } void main() { auto b = new B; } ``` throws: Error: constructor `onlineapp.A.this` missing initializer for immutable field i Error: cannot modify immutable expression this.i Why can't I initialize the immutable member in the derived class? Because by the time B's constructor is called, A might already have initialized it, and rely on it never changing. The solution is to add a constructor overload to A, and call that from B: class A { immutable int i; protected this(int i) { this.i = i; } } class B : A { this() { super(3); } } unittest { auto b = new B; } -- Simen