digitalmars.D - Constructor inheritance? Why not?
- Tofu Ninja (2/2) Jun 07 2015 Is there any reason why constructors are not inherited? All other
- Jonathan M Davis (9/11) Jun 07 2015 They're not polymorphic, and it doesn't make sense to call a base
- Tofu Ninja (6/17) Jun 07 2015 Their are plenty of examples where you would want a constructor
- Jonathan M Davis (35/40) Jun 07 2015 In most cases, you need to create a new constructor, because it's
- Tofu Ninja (22/56) Jun 07 2015 I am not sure why you think its a rare case, I hit it all the
- Jonathan M Davis (34/37) Jun 07 2015 I expect that it originally comes down to the fact that
- Tofu Ninja (30/69) Jun 08 2015 I suppose I just see it differently. I see no reason why
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (11/27) Jun 08 2015 They can if you use type variables. Type variables can be virtual
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (11/15) Jun 08 2015 And IIRC you can emulate type variables in D too if you dig into
- Paulo Pinto (5/33) Jun 08 2015 Yep, in Modula-3 and Oberon, one even has to create the VMT
- Atila Neves (6/17) Jun 07 2015 Yes, modern C++ allows you to inherit constructors. It makes
- Shachar Shemesh (9/12) Jun 08 2015 No, it didn't.
- Kapps (12/14) Jun 08 2015 It should be relatively easy to do this with a mixin in theory.
Is there any reason why constructors are not inherited? All other methods are inherited, why not constructors?
Jun 07 2015
On Monday, 8 June 2015 at 02:39:22 UTC, Tofu Ninja wrote:Is there any reason why constructors are not inherited? All other methods are inherited, why not constructors?They're not polymorphic, and it doesn't make sense to call a base class constructor on a derived class. I think that I heard somewhere that C++11 added some sort of constructor inheritance, so maybe there's something we could do that would make sense, but in general, I don't see how the concept makes any sense at all. Construction is intimately tied to the type being constructed. It's as non-generic as you can get. - Jonathan M Davis
Jun 07 2015
On Monday, 8 June 2015 at 03:35:52 UTC, Jonathan M Davis wrote:On Monday, 8 June 2015 at 02:39:22 UTC, Tofu Ninja wrote:Their are plenty of examples where you would want a constructor to be inherited, exceptions being a good one. Currently if you have a base class with a constructor that you want all the sub classes to have as well, you simply have to just copy past them all over the place.Is there any reason why constructors are not inherited? All other methods are inherited, why not constructors?They're not polymorphic, and it doesn't make sense to call a base class constructor on a derived class. I think that I heard somewhere that C++11 added some sort of constructor inheritance, so maybe there's something we could do that would make sense, but in general, I don't see how the concept makes any sense at all. Construction is intimately tied to the type being constructed. It's as non-generic as you can get. - Jonathan M Davis
Jun 07 2015
On Monday, 8 June 2015 at 04:16:14 UTC, Tofu Ninja wrote:Their are plenty of examples where you would want a constructor to be inherited, exceptions being a good one. Currently if you have a base class with a constructor that you want all the sub classes to have as well, you simply have to just copy past them all over the place.In most cases, you need to create a new constructor, because it's a different type with different data, even if some of the constructor parameters might be the same. Exceptions are a rare case where the constructors are frequently the same, because frequently with exceptions all you care about is the type itself, not additional data. But that's far from normal. Certainly, if there's any kind of constructor inheritance, I think that it needs to be explicit, because otherwise, you'll accidentally end up with constructors that you don't even know you have. But while it might be nice to avoid boilerplate in exception code, I question that it's worth much in the general case, because it's only useful when you don't have additional data that needs to be passed to the constructor of a derived class. Regardless, we're talking about syntactic sugar here. Maybe it's worth adding. Maybe not. But the primary reasons that we don't have it are because the languages before us didn't it (meaning that we're less likely to have thought of it), and because it's not actually needed, so we can get by fine without it. But the type of "inheritance" that you're talking about with constructors is fundamentally different from the type of inheritance that you get with other functions, so I don't think that the fact that we have class inheritance makes it at all obvious that we would have constructor inheritance or even that we should have it. Really, it's just a question of whether this particular bit of syntactic sugar is worth adding (which is debatable). It's not something fundamental about how class inheritance and polymorphism work. I expect that if someone came up with a good DIP for this and implemented a PR for it that they'd stand a reasonable chance of getting it into the language, but it's not exactly something that folks have been screaming for. - Jonathan M Davis
Jun 07 2015
On Monday, 8 June 2015 at 04:32:41 UTC, Jonathan M Davis wrote:In most cases, you need to create a new constructor, because it's a different type with different data, even if some of the constructor parameters might be the same. Exceptions are a rare case where the constructors are frequently the same, because frequently with exceptions all you care about is the type itself, not additional data. But that's far from normal.I am not sure why you think its a rare case, I hit it all the time. Something where I don't want to change much in the sub class other then maybe override a method or something.Certainly, if there's any kind of constructor inheritance, I think that it needs to be explicit, because otherwise, you'll accidentally end up with constructors that you don't even know you have.I fail to see how that would be a problem, you have the same thing with normal methods.But while it might be nice to avoid boilerplate in exception code, I question that it's worth much in the general case, because it's only useful when you don't have additional data that needs to be passed to the constructor of a derived class.A lot of the time when I add new data to a class, I will just statically initialize it, in those cases this would still be useful.Regardless, we're talking about syntactic sugar here. Maybe it's worth adding. Maybe not. But the primary reasons that we don't have it are because the languages before us didn't it (meaning that we're less likely to have thought of it), and because it's not actually needed, so we can get by fine without it.Would save time and reduce copy past errors, I see value in that.But the type of "inheritance" that you're talking about with constructors is fundamentally different from the type of inheritance that you get with other functions, so I don't think that the fact that we have class inheritance makes it at all obvious that we would have constructor inheritance or even that we should have it.I don't really see how its any different, define a constructor in a base. Gets inherited, if you want it to do something different then you override it, have the option to call the base version like normal overriding does(only difference is that at least some version of the base needs to be called which is actually a feature that other methods could benefit from having). The only use that would be slightly different is it would be harder to get polymorphism out of it(still possible if you you want to allocate and deffer construction to a later time).Really, it's just a question of whether this particular bit of syntactic sugar is worth adding (which is debatable). It's not something fundamental about how class inheritance and polymorphism work. I expect that if someone came up with a good DIP for this and implemented a PR for it that they'd stand a reasonable chance of getting it into the language, but it's not exactly something that folks have been screaming for.No its definitely not something that alot of people seem to care about, but I always found it odd that constructors get certain special casing like this.
Jun 07 2015
On Monday, 8 June 2015 at 06:04:23 UTC, Tofu Ninja wrote:No its definitely not something that alot of people seem to care about, but I always found it odd that constructors get certain special casing like this.I expect that it originally comes down to the fact that constructors aren't polymorphic and _can't_ be polymorphic. When you override a function, you're overriding the one in the base class and replacing its implementation. You can choose to call the base class' version of the function, but you don't have to. You're dynamically replacing a function. Constructors, on the other hand, do _not_ override. A constructor must exist in _every_ class in the inheritance tree, and they all have to be called - and called in the right order. When you "inherit" a constructor, you're not overriding the one in the base class. You _still_ have to have constructors in both the base class and derived class. You're just telling the compiler to insert a constructor into the derived class which has exactly the same parameters as one in the base class and which simply forwards its arguments to the base class' constructor. There's no polymorphism involved at all. It's simply syntactic sugar to avoid having to type out the whole constructor implementation yourself. There's nothing dynamic about it all. Inherited constructors are truly just syntactic sugar. So, while they may be useful (as syntactic sugar often is), they add _zero_ functionality, unlike virtual functions. So, yes, constructors _are_ fundamentally different from other functions. And the inheritance that you get with constructors is not at all what you get when you override a function. They're at most superficially similar. And older languages such as C++98 and Java don't have inherited constructors. They're a relatively new idea. So, if anything, it would be surprising if D had them. Constructors are just different beasts from other functions (the same goes for destructors). And while D has lots of new ideas in it, it's not like we have all of the cool, new language ideas out there. Maybe we'll get constructor inheritance someday, but no one has cared enough to add it thus far. - Jonathan M Davis
Jun 07 2015
On Monday, 8 June 2015 at 06:35:33 UTC, Jonathan M Davis wrote:On Monday, 8 June 2015 at 06:04:23 UTC, Tofu Ninja wrote:I suppose I just see it differently. I see no reason why constructors need to be different from normal virtual methods other than the small requirement that they need to call their base if they override. That requirement is not really something specific to constructors either, plenty of other types of functions would benefit from that sort of guarantee. Constructors need not exist in every instance of the tree, if the class implementor deemed the base constructor to be sufficient then that should be allowed. Plenty of times people will just insert empty constructors in sub classes that only forward arguments to the base. That forwarding constructor is not needed, just call the base constructor in the same way normal virtual methods work. Also constructors certainly can be polymorphic and the aforementioned base call guarantee does not make it so that they cant. Deferred construction certainly allows for polymorphic construction. Aka allocate and set up static information(including type information) without calling a constructor so that it can be called at a later time. In the time between allocation and construction, that instance could be assigned to reference of the base type and construction could be polymorphic. The only issue one would have with this is if a base constructor's signature was no long sufficient to fully construct the object, in which case it would make sense to just override and throw an exception the same way you would restrict any method signatures usage. That solution though wouldn't really work for D at this point which is why it would probably make more sense to make it opt-in at the base class level.No its definitely not something that alot of people seem to care about, but I always found it odd that constructors get certain special casing like this.I expect that it originally comes down to the fact that constructors aren't polymorphic and _can't_ be polymorphic. When you override a function, you're overriding the one in the base class and replacing its implementation. You can choose to call the base class' version of the function, but you don't have to. You're dynamically replacing a function. Constructors, on the other hand, do _not_ override. A constructor must exist in _every_ class in the inheritance tree, and they all have to be called - and called in the right order. When you "inherit" a constructor, you're not overriding the one in the base class. You _still_ have to have constructors in both the base class and derived class. You're just telling the compiler to insert a constructor into the derived class which has exactly the same parameters as one in the base class and which simply forwards its arguments to the base class' constructor. There's no polymorphism involved at all. It's simply syntactic sugar to avoid having to type out the whole constructor implementation yourself. There's nothing dynamic about it all. Inherited constructors are truly just syntactic sugar. So, while they may be useful (as syntactic sugar often is), they add _zero_ functionality, unlike virtual functions. So, yes, constructors _are_ fundamentally different from other functions. And the inheritance that you get with constructors is not at all what you get when you override a function. They're at most superficially similar. And older languages such as C++98 and Java don't have inherited constructors. They're a relatively new idea. So, if anything, it would be surprising if D had them. Constructors are just different beasts from other functions (the same goes for destructors). And while D has lots of new ideas in it, it's not like we have all of the cool, new language ideas out there. Maybe we'll get constructor inheritance someday, but no one has cared enough to add it thus far. - Jonathan M Davis
Jun 08 2015
On Monday, 8 June 2015 at 06:35:33 UTC, Jonathan M Davis wrote:On Monday, 8 June 2015 at 06:04:23 UTC, Tofu Ninja wrote:They can if you use type variables. Type variables can be virtual too.No its definitely not something that alot of people seem to care about, but I always found it odd that constructors get certain special casing like this.I expect that it originally comes down to the fact that constructors aren't polymorphic and _can't_ be polymorphic.When you override a function, you're overriding the one in the base class and replacing its implementation. You can choose to call the base class' version of the function, but you don't have to. You're dynamically replacing a function.Conceptually you should. In Simula's successor Beta you had to, but you had "inner" inheritance opposed to Simula/C++ "outer" inheritance. E.g. the logic of the subclass is executed by the superclass. It is much cleaner, actually.So, yes, constructors _are_ fundamentally different from other functions. And the inheritance that you get with constructors is not at all what you get when you override a function. They're at most superficially similar. And older languages such as C++98 and Java don't have inherited constructors. They're a relatively new idea.Let's not rewrite history, shall we? Constructors are not fundamentally different from other functions by nature. In minimal OO languages there is no significant difference between the definition of a class/constructor and a function.
Jun 08 2015
On Monday, 8 June 2015 at 09:20:06 UTC, Ola Fosheim Grøstad wrote:They can if you use type variables. Type variables can be virtual too.And IIRC you can emulate type variables in D too if you dig into RTTI, but I don't quite remember where I found that. I am sure you know how to do it. IIRC it was not difficult. You might want to look into that and polymorphic construction as a library feature, it allows for dynamic generics. Not for every day use, but allows some advanced modelling.but you had "inner" inheritance opposed to Simula/C++ "outer" inheritance.Actually Simula has "inner" inheritance for the constructor and not for the virtual functions, when I think of it, wheras Beta is more consistent and have "inner" semantics on both. C++ just messed that up in the translation.
Jun 08 2015
On Monday, 8 June 2015 at 09:20:06 UTC, Ola Fosheim Grøstad wrote:On Monday, 8 June 2015 at 06:35:33 UTC, Jonathan M Davis wrote:Yep, in Modula-3 and Oberon, one even has to create the VMT explicitly. -- PauloOn Monday, 8 June 2015 at 06:04:23 UTC, Tofu Ninja wrote:They can if you use type variables. Type variables can be virtual too.No its definitely not something that alot of people seem to care about, but I always found it odd that constructors get certain special casing like this.I expect that it originally comes down to the fact that constructors aren't polymorphic and _can't_ be polymorphic.When you override a function, you're overriding the one in the base class and replacing its implementation. You can choose to call the base class' version of the function, but you don't have to. You're dynamically replacing a function.Conceptually you should. In Simula's successor Beta you had to, but you had "inner" inheritance opposed to Simula/C++ "outer" inheritance. E.g. the logic of the subclass is executed by the superclass. It is much cleaner, actually.So, yes, constructors _are_ fundamentally different from other functions. And the inheritance that you get with constructors is not at all what you get when you override a function. They're at most superficially similar. And older languages such as C++98 and Java don't have inherited constructors. They're a relatively new idea.Let's not rewrite history, shall we? Constructors are not fundamentally different from other functions by nature. In minimal OO languages there is no significant difference between the definition of a class/constructor and a function.
Jun 08 2015
On Monday, 8 June 2015 at 03:35:52 UTC, Jonathan M Davis wrote:On Monday, 8 June 2015 at 02:39:22 UTC, Tofu Ninja wrote:Yes, modern C++ allows you to inherit constructors. It makes sense when you want to avoid the boilerplate of a constructor that does nothing but forward to the base class's constructor with the same signature. AtilaIs there any reason why constructors are not inherited? All other methods are inherited, why not constructors?They're not polymorphic, and it doesn't make sense to call a base class constructor on a derived class. I think that I heard somewhere that C++11 added some sort of constructor inheritance, so maybe there's something we could do that would make sense, but in general, I don't see how the concept makes any sense at all. Construction is intimately tied to the type being constructed. It's as non-generic as you can get. - Jonathan M Davis
Jun 07 2015
On 08/06/15 06:35, Jonathan M Davis wrote:They're not polymorphic, and it doesn't make sense to call a base class constructor on a derived class. I think that I heard somewhere that C++11 added some sort of constructor inheritanceNo, it didn't. What C++11 added was the ability to use the implementation of one constructor from another (something D already has), and to use the parent's constructor definitions without redefining them when you have several. None of those comes under the umbrella of "constructor inheritance", for much the same reasons you already pointed out. Shachar
Jun 08 2015
On Monday, 8 June 2015 at 02:39:22 UTC, Tofu Ninja wrote:Is there any reason why constructors are not inherited? All other methods are inherited, why not constructors?It should be relatively easy to do this with a mixin in theory. Or even a CtorArgsTuple, allowing something like (not certain if this would work): this(CtorArgsTuple!super args, bool animated) { super(args); this.animated = animated; } Also not sure if the '!super' would work as opposed to specifying the type. This approach has the issue of not inheriting documentation though, which annoys me.
Jun 08 2015