I broke generics.
Monkey Forums/Monkey Programming/I broke generics.
| ||
Interface IA Method DoA:Void() End Class EntityBase Implements IA Field a:IA Method DoA:Void() a.DoA() End End Class Entity<IA> Extends EntityBase Field a := New IA() End Class A0 Implements IA Method DoA:Void() Print "A0" End End Class A1 Implements IA Method DoA:Void() Print "A1" End End Function Main() Local entity := New Entity<A0> entity.DoA() End "Memory Access Violation," even in debug mode. Exciting stuff. |
| ||
Okay so I experimented some more, importing the reflection module caused an actually useful error.Field 'a' in Entity<A0> overrides existing declaration in class EntityBase. I guess the second 'a' Field was never even included in the build, and the memory access violation was for calling a method of a Null object. |
| ||
I achieved the architecture and functionality I wanted with something like this. |
| ||
Looking at the code, monkey is just silently dropping the initialisation of 'a' in the subclass when there's an override. I'd say that's a bug. Has narrowing of generics by type been implemented in v67? If not that code probably isn't doing what you think. 'IA' is just being used as a type alias in the same way that 'T' is. You can put any object in as the generic initialiser (although it'll fail on the assignment in your last structure). |
| ||
I wasn't aware what the term ("narrowing") was for that until now. I had been doing that because I thought that was how to make sure that the <class> had a DoStuff() method but you're right it doesn't work like I thought. |
| ||
I wasn't aware what the term ("narrowing") was for that until now. I just picked a word that seemed descriptive. I don't know if there is an "official" term for it. Java calls them bounded types. |
| ||
I do a lot of tests to see what kind of architectures can be managed with odd arrangements of generics and interfaces and reflection. Bounded types sounds like a nifty feature. One of my experiments was to see if you could have something like Field member:{IA, IB} Where any object can be put in the member field as long as it is an instance of a class that implements both Interface IA and Interface IB. Could bounded types allow this kind of thing? Or are they only ever used in generics. It seems like it could be done pretty easily but I have absolutely no knowledge about how type-checking is done under the hood. An easy workaround would be to make Interface InterfaceAB Extends InterfaceA, InterfaceB End But then you'd have to make a new interface for every combination of Interfaces. To make a class valid for these kinds of assignments they'd have to look like this: Class MyClass Implements A, B, C, AB, AC, BC, ABC An instance of this class could go in any slot that requires some or all of the possible interfaces. But it seems like there should be a better way. Compound interfaces could be generated the same way generics are built, and then added to any class that implements those two interfaces. I dunno, I'm just brainstorming. |