[Mono-devel-list] overriding return type

Alan Jenkins Alan.Jenkins at phonecoop.coop
Sat Jul 26 11:06:46 EDT 2003


I totally agree that neither of us are OO experts, and I'd like to add that 
I've not exactly been an expert communicator either.  Thanks for taking the 
time to disagree with me, especially as you've done all the code in your 
head.

5,000 .cs files, you say! Thats a lot of code.  I didn't mean to imply that 
the class library would be written or compiled using this feature - 
implementing a compatable clone of a class library must be hard enough 
without having to use a slightly different language to the original.  Mono 
might strike off in its own direction at some point, but diverging from MS 
.NET is not a good idea at the moment.  Leave that for later, when Mono has 
become the standard implementation of .NET (smile, but don't laugh - look at 
GNU/Linux and Unix).  Thats why I didn't say "please consider adding this 
feature in the next version" - I am interested in it mainly for selfish 
reasons, and it could well break the ECMA standard.

I accept that any idea like this is potentially dangerous, and must be 
examined carefully - but thats one of the reasons why it would be an 
extremely good idea to make it an optional feature.  I don't think there are 
(bad) implications which would only become obvious with multiple derivatives, 
and the additional complexity caused by extra derivative classes would not 
become execessive.

I agree that there must be a reason why this feature is not present in the C# 
(and Java) compiler, even though CIL does support it.  I've done some 
serching on the web, and I think C++ will let you do this, but thats not 
saying much (what doesn't C++ let you do?):

//test.cpp - compiles sucessfully on my computer.
int main() {	}

class Example1 {
	virtual Example1 *Method() {
		return new Example1();
	}
};

class B : public A {
	virtual Example2 *Method() {
		return new Example2();
	}
};
//test.cpp ends

---

Could you please clarify some of your comments?

>> // This works because IList2 implements IList
>> IList list = GetList.NewList();

don't you mean "because IList3 implements IList"?

>> // This causes a casting error because our list is an IList3 
>> // and its Iterator() method returns an IIterator3 object. The 
>> // correct thing is for Iterator to return an IIterator object, and
>> // check to see if it can be upcast to IIterator2
>> IIterator2 iterator2 = list.Iterator();

Did you mean a runtime or a compile time error?  I assume you mean a runtime 
error, from the way you put it, and from your other comments.
I would have thought you would get a compile time error, because what you are 
doing is implicitly upcasting IIterator to IIterator2.

I think I understand the detail of your example, but not the reason for coding 
it this way.

Your last line implicitly assumes that the return value of GetList.New() is an 
IList2 - thats why it fails.  Surely its better to express this assumption 
explicitly:

//results in compile time cast error: implicit upcast
IList2 list = GetList.NewList();

//results in runtime error: explicit upcast failure
IList2 list = (IList2) GetList.NewList();

Neither do I understand why GetList.NewList() has a return type of IList, when 
it always returns an object of type IList3.  I would have thought that it 
would have made more sense to give it a return type of IList3, so that it was 
both obvious and certain that it would return an IList3 object.

GetList.NewList() doesn't return a suitable list for the operations performed 
on it - NewList(), and/or the code using it is flawed.  You assert that the 
correct fix is to change the return type of IList2.Iterator() and 
IList3.Iterator() to IIterator, and for calling code to upcast the result. 
Essentially, you remove the strict obligation on implementors of 
IList2.Iterator() and IList3.Iterator() to return an appropriate iterator, 
and presumably make the obligation known through comments or attributes.  
Surely this is more error prone, not less, just as the requirement in Java to 
explicity define the exceptions thrown by specific methods eases development 
(esp. debugging).

The assumptions made by the calling code are expressed (as far as I can see) 
in such a way as to cause a compile time error.  I understand that if similar 
assumptions caused runtime errors they could be difficult to fix, but I think 
it would be fairly easy to avoid them altogether.  I would have thought that 
your solution is more likely to result in runtime errors (when explicitly 
upcasting the return value of a method), whereas if you can override return 
types, you are more likely to catch the errors at compile time (implicit 
upcasts).



More information about the Mono-devel-list mailing list