Out of curiosity, what is wrong with Scala's method to handle this problem (where only the concrete types can have constructors)? From the thread you linked, it seems like the main complaint against doing so would create a stronger coupling between the abstract and concrete types than desired.
However, I think the grouping method suggested above creates the same problem. Sure, you can create a layer of abstraction with a getter/setter. However, if you're really worried about fields disappearing, the grouping method creates more work (you not only change to type, but you have to alter the getters/setters). Also, it seems like the separation between structure and behaviour is already broken by having concrete types. Allowing a explicit declaration of a structure hierarchy of what you are already doing implicitly with the grouping doesn't change the structure/behaviour relationship to me. If you couldn't group and if there weren't concrete types, then I would have to agree with you. Thanks for listening! On Saturday, June 21, 2014 11:35:53 AM UTC-4, Stefan Karpinski wrote: > > In particular, I think the constructor issue cuts to the heart of the > matter. If you have any good thoughts on that, it might help revive that > discussion. So far the best proposal for subtype construction in the > presence of abstract types with fields basically leads you to the "parent" > structure as leading field pattern that's been suggested here. > > On Jun 21, 2014, at 11:23 AM, Stefan Karpinski <[email protected] > <javascript:>> wrote: > > It's non-orthogonal because subtyping becomes about sharing both behavior > and structure, not just behavior. An orthogonal approach would use an > independent feature for sharing structure. This is all covered in the > discussion in https://github.com/JuliaLang/julia/issues/4935. > > On Jun 21, 2014, at 9:59 AM, Abe Schneider <[email protected] > <javascript:>> wrote: > > I think that's a fair point (though I may disagree that it's > non-othogonal). My main point is that you are already implicitly using a > hierarchical structure with grouping. Therefore, I don't see this as adding > a new feature to the language, it's already something you can do in Julia, > but rather providing the syntax to allow the relationship to be declared in > useful way. > > The code: > abstract A > x::Int64 > end > > type B <: A > y::Int64 > end > > type C <: A > z::Float64 > end > > > is much clearer to me than: > type A > int x::Int64 > end > > abstract AType > getx(a::AType) = a.x > setx(a::AType, x::Int64) = a.x = x > > type B <: AType > parent::A > end > > type C <: AType > parent::C > end > > > or: > abstract A > > type B <: A > x::Int64 > y::Int64 > end > > type C <: A > x::Int64 > z::Float64 > end > > > The last two examples violate DRY, make for potentially difficult to > maintain code, and are less obvious to someone else looking at the code as > to what is happening. > > On Saturday, June 21, 2014 9:02:52 AM UTC-4, Stefan Karpinski wrote: >> >> The harm is adding unnecessary, non-orthogonal language features. We've >> tended not to add features until it becomes very clear that we need them >> and why, and that's been a good approach so far. Aside from several >> discussions similar to this, I don't feel like the problems this feature >> would alleviate are especially pressing. So far subtyping in Julia is >> purely about behavior, not structure and changing that even a little bit >> would require some significant motivation – certainly more than "why not?" >> >> On Jun 21, 2014, at 8:45 AM, Abe Schneider <[email protected]> wrote: >> >> After some thought, it occurred to me that with the grouping you >> suggested, you are really implementing a type of inheritance. If you rename >> your sub-type as 'parent' you have: >> >> type ParentClass >> # vars >> end >> >> abstract ParentClassType >> >> type ChildClass <: ParentClassType >> parent::ParentClass >> # vars >> end >> >> which is exactly what a Mixin paradigm would accomplish, only that the >> compiler would help with the construction (which at the end of the day is >> all OOP really is). If this type of construction can be done by hand, I'm >> not sure what the harm is in having the compiler make things easier. >> >> On Saturday, June 21, 2014 3:09:36 AM UTC-4, Tobias Knopp wrote: >>> >>> When I switched from C++ to C# I had a similar opinion about the issue >>> of duplicated fields in all classes implementing an interface. But when >>> getting used to grouping things together and using has-a relations this has >>> changed my thinking about it. >>> I now think that it enforces structuring code in a sane way. When >>> inheriting field members one often observes far to late that one has >>> structural issues and refactoring then becomes really hard. >>> >>> When looking at Julia base code (or several of the packages) one will >>> see that the issue of inheriting field members does not come up so much. >>> >>> One side comment. In Julia the possibility to use duck typing gives a >>> lot of flexibility. And when one reaches limits (e.g. due to the absence of >>> abstract multiple inheritance) duck typing is often a solution. >>> >>> Am Samstag, 21. Juni 2014 03:43:57 UTC+2 schrieb Abe Schneider: >>>> >>>> I agree, I think it's the best solution given the tools (and what I'm >>>> going to use for my code). However, it still feels more like a hack around >>>> the design than good programming practice. >>>> >>>> On Friday, June 20, 2014 5:41:02 PM UTC-4, Spencer Russell wrote: >>>>> >>>>> I'd just like to second Jameson's suggestion of aggregating the common >>>>> fields into a type that all your subclasses contain. >>>>> >>>>> I did quite a bit of thinking on this issue when it came up in >>>>> AudioIO, and was lucky enough to have both Jeff and Stefan around to >>>>> bounce >>>>> ideas off of. >>>>> >>>>> My main issues with the duplicated data in subclasses were: >>>>> >>>>> 1. It's annoying to have to add the same set of fields every time >>>>> you define a subtype, and violates DRY. It's also error prone. >>>>> 2. If you want to add a feature to the base type that requires a >>>>> new field, EVERYONE WHO EVER SUBTYPED your base type now has to add >>>>> the >>>>> field to their subtype. It's bad enough when this is within your own >>>>> codebase, but if there's other code subtyping it then you're really in >>>>> trouble. >>>>> >>>>> Encapsulating the common fields solves both those issues.If you want >>>>> to add new fields later on you can just add them to the aggregating type. >>>>> Most importantly, it does it in really easy-to-reason-about way, without >>>>> adding any tricky edge cases or complicated rules for developers to >>>>> understand. >>>>> >>>>> peace, >>>>> s >>>>> >>>>> >>>>> On Fri, Jun 20, 2014 at 3:57 PM, Abe Schneider <[email protected]> >>>>> wrote: >>>>> >>>>>> I was thinking something along those lines, but as was pointed out, >>>>>> you would have to also create the constructors. >>>>>> >>>>>> Unfortunately, I'm on my phone right now, so I can't effectively post >>>>>> code. I was thinking of a 'mixin' macro which would create a new type >>>>>> (with >>>>>> constructor): >>>>>> >>>>>> @mixin Foo <: Bar Baz >>>>>> >>>>>> Would create Foo from both Bar and Baz. However, because there is no >>>>>> MI, you could only inherit from Bar. >>>>>> >>>>>> While it does have some magic to it, it might not be awful. Also, you >>>>>> could still make an outer constructor for it. >>>>>> >>>>>> Of course, I don't know the actual technical challenges to making it, >>>>>> since I haven't had time to write any code. >>>>>> >>>>> >>>>>
