Covariant property types?
Quick question for the language nuts out there.
Java and C++ both have the notion of covariant return types when overriding.
Typically, the rule is that an overridden method in a subclass can have a return type that is more specific than its superclass, like so (written in AS-like pseudocode).
class Application { function getMenu() : Menu } class MyApp extends Application { override function getMenu() : MyMenu }
This is allowed because MyApp honors the contract originally specified by the Application class. The getMenu() function is returning a Menu. However, because it is defined as returning a more specific type of Menu, further type checking can be done, and you can get better code hints when you know that you are using an object of type MyApp.
Some languages also allow changing the type of arguments to functions. In these cases, the arguments have to be contravariant, not covariant (wider, not narrower).
class Menu extends UIComponent { // blah blah blah } class Application { function setMenu(newMenu: Menu) } class MyApp extends Application { override function setMenu(newMenu: UIComponent) }
The MyApp subclass honors the contract specified by the Application superclass, because it allows you to call setMenu with any object of type Menu. It widens the definition of setMenu to, in this case, allow any UIComponent to be passed in. Callers who were expecting MyApp to behave like a traditional Application would be none the wiser, but callers who knew the special abilities of the MyApp class could take advantage of its super powers.
I would love to add these types of language features to ActionScript, but the problem is that I want to use them for properties, and the usual recipe doesn’t work so well.
class Application { function get menu() : Menu; function set menu(menu: Menu); } class MyApp extends Application { override function get menu() : MyMenu; override function set menu(menu: OOPS???); }
I am not a language guy, but I would love to be able to have the freedom to redefine a read/write property with a covariant (narrower) type. What this means is that setting the property with the wrong value may lead to a runtime exception. However, there are many cases where these values are either only set once (at the creation of an object) or only within controlled situations.
In the example pseudocode above, I’d love to be able to have, for example, a generic “menu” property of Application that I could do generic things with. But within my subclass, I’d like to have the type of the menuproperty be the actual class I’m using for my menu, so I can do things like: myApp.menu.specialFadeEffect() without downcasting.
Any language geeks out there? Is allowing covariant read/write property types when overriding a bad idea?
I don’t think I qualify as a language geek, but I would think that it is a bad idea for the reasons you specify above. It basically breaks the inheritance contract (that a collaborator can blindly work with a subclass of it’s expected type). You could potentially support it for read only properties, but that would be a bit quirky.
It would be great to have support for covariant return types in AS though (and the much less frequently used contravariant parameters).
Don’t let these language features distract you from inherited static members and a more flexible proxy model (multiple inheritance?) though. :)
Cheers,
Grant.
I think that it would profiliate use of “universal” frameworks that would add confusion. If you want “*” type for menu just say so and do not worry if anyone gets it wrong – it will blow in their face on the first use.
I would rather settle for different thing for application development – just a compiler tweak rather then language – accomplishing the same.
… application.menu.specialFadeEffect()
Would simply work – and will essentially be more applicable and natural to application developers that are not language nuts.
A bit more work for overworked MXML compiler to create “dynamic” wrapper class unless you are top level – but just enough rope for application developers that are in a rush and need quick fix.
Sincerely,
Anatole Tartakovsky
Thanks for the post, Anatole!.
If you want method calls to just work in all cases, I think you can accomplish this today by removing the -strict option when compiling.
One question, though.. don’t you want strong type checking? I personally like the fact that the compiler (and the tool) know what methods are available, as well as proper parameters, etc. My intention in thinking about covariant properties was to try to extend strong type checking to more cases.
Grant: for some reason, not having inherited statics doesn’t bother me, but I agree that it’s annoying. Not 100% sure what you mean by a more flexible proxy model, and I’d love to hear about it. Multiple inheritance? Ack! Maybe a mixin
model instead?
Inherited statics can be very handy for utility classes, and for value constants when subclassing.
Regarding the flexible proxy model: while __resolve had it’s own set of issues, one of the nice things about it was that any object type could act as a proxy. AS3 is very limiting in this respect – you need to inherit from proxy. This causes a number of problems, most importantly that you cannot have a DO that acts as a proxy. I’m not big on multiple inheritance, it was mostly a cynical suggestion to resolve the above issue.
Cheers.
[…] I just read a post on Sho Kuwamoto’s blog, in which he writes that covariance and contravariance are not (yet?) allowed when overriding methods in Actionscript. Even though I had previously not even ever heard of the terms, I would have thought that covariance at least would’ve been included, with AS3 being the wow-ish new version of Actionscript and all that.. […]
Dealing with asynchronous events,