5 ms·
Well, derived classes are meant to be drop-in replacement for the base class. In that sense it totally makes sense that you can't have a non-generic child class
by jkrems 12y ago
Well, derived classes are meant to be drop-in replacement for the base class. In that sense it totally makes sense that you can't have a non-generic child class of a generic base class. Otherwise it encourages design where classes are treated as method dumps.
- bjeanes 12y agoExactly what I was going to say. This seems like a good design decision, especially because the typealias hack offers a work around if you really need to.
- barrkel 12y agoDon't mix up your polymorphism. The fact that an instance of A is assignment compatible with a location of type B does not imply that a class of type A is assignment compatible with a location of type class of B. This is not the case for languages like C#, Java, C++ etc. (despite those languages not having class types); if a subclass does not define all the constructors of its ancestor class, the subclass is not a "drop-in replacement". Delphi does have class value polymorphism that mirrors instance polymorphism, and it can be a source of confusion, not to mention type holes. For A inheriting from B, you can construct a value of type A using a constructor of B if you assign A to a location of type class of B; A's constructor won't run, and its assumptions and invariants won't necessarily hold. It's one of several problems that makes designing robust classes in Delphi awkward.
- twic 12y agoNo. If the child class binds the type parameter of the base class (as in this example), then it's meaningless to think of that class as being generic. In this example, Bar is always Bar<String> - you can't have a Bar<Integer> or a Bar<anything else>. So why not just call it Bar? FWIW, this is how it works in Java, and it seems to work. Indeed, calling it Bar<String> seems really weird to me. Usually, in a declaration, the thing inside the angle brackets is a the name of a parameter, which can assume various values at runtime: class Foo<T> But in the subclass, it's the name of a type: class Bar<String> Essentially, one is a declaration, and the other is an expression. Like and l-value and an r-value. I don't think i've ever seen a language which allows both of those in the same place.
- jkrems 12y agoI don't think Java is a good example for OOP best practice. For exactly these reasons. I can't think of a reason this should be allowed. It screams "I'm trying to misuse class hierarchy to do specialization instead of using composition".
- pietro 12y agoNot classes; instances. So instances of Foo : Bar<T> should be drop-in replacements for instances of Bar<T>.