Re: Covariant Return Types
[email protected] Tue, 24 Feb 2004 18:48:36 -0600
| Newsgroups | gmane.comp.lang.nice.general |
|---|---|
| Message-ID | <[email protected]> |
Quoting Arjan Boeijink <[email protected]>: > > Now, how many =self= methods do we have? One method with two > > implementations? Or two methods, with the first one having two > > implementations and the second one having one implementation. > > From typechecking / resolving point of view there are 2 methods > but for dispatching it's one method. Let's ask the question a different way. If I have: package a; class A { } class B extends A { } A self(A a) = a; B self(B b) overrides A self(A) = b; void main(String [] args) { let x = self(A); // syntax? let y = self(B); // syntax? println(x == y); } Do I get "true" or "false"? If it is "true" then I would say there is one method and if it is "false" I would say there are two methods. This is mostly just a terminology thing though. > >If so, it isn't much different than: > > package a; > > public class A { } > > public class B extends A { } > > public A self(A a); > > B anothername(B b) overrides A self(A a); > > self(A a) { log("A -> A"); return a; } > > anothername(B b) { log("B -> B"); return b; } > >That is, allowing specialization of a method by another method that doesn't > even > >have the same name. > > This would be doable but it will yield new problems for example adding an > implementation like: > self(B a) { return new A(); } It doesn't introduce any new problem that I see. The error would be: line 7, column 1: Ambiguity for method examples.A self(A a) both line 10, column 1: self([email protected]) and line 9, column 1: anothername([email protected]) match for parameters of type (examples.B). vs. line 7, column 1: Ambiguity for method examples.A self(A a) both line 10, column 1: self([email protected]) and line 9, column 1: self([email protected]) match for parameters of type (examples.B). It could also come in handy for cases where the method we want to override is already overloaded (see below). > >Do we want clients of this package to know that the second implementation > >even exists? > > If the client can add implementations for that method it needs to know which > implementations exist. > When adding self(B a) { ... } in the client package the compiler will give > an ambiguous implementation error at coverage testing. So, then we can conclude that visibility modifiers only make sense for method declarations, not for method implementations, right? So that: public A self(A a) { ... } private self(B b) { ... } should be disallowed, the correct syntax would be: public A self(A a) { ... } self(B b) { ... } > >I guess this doesn't work in cases where the method we want to override has > >already been overloaded: > > > > package c; > > class A { } > > A doSomething(A a) { ... } > > > > package d; > > import c; > > void doSomethingElse(A a) { ... } > > > > package e; > > import c; > > void doSomethingElse(A a) { ... } > > > > package f; > > import c; > > import b; > > import c; > > class B extends A { } > > B doSomething(B a) { ... } > > doSomethingElse(B b) { ... } > > > > Similarly, we should be able to say whether f.doSomethingElse(B) > >is a specialization of d.doSomethingElse(a) or e.doSomethingElse(A). > > Yes, maybe using the fully qualified method name for that like: > d.doSomeThingElse(B b) { ... } Okay, but try this version: package c; interface A { } interface B { } A doSomething(A a) { ... } B doSomething(B b) { ... } package d; import c; class C implements A, B { } override c.doSomething(C a) { ... } Now, does d.doSomething(C) override c.doSomething(A) or c.doSomething(B)? Notice in the old specialization syntax, the last line would be: override c.doSomething(a@C); And then, we could generalize the syntax to: override c.doSomething(A a@C); which would make it obvious that we are specializing c.doSomething(A). Also, notice that when the package name is long, it is ugly to provide many specializations using that syntax. > > But, should we be able to say that f.doSomethingElse(B) is a specialization > of _both_?: > > doSomethingElse(B b) overrides d.doSomethingElse(A), > > e.doSomethingElse(A) { ... } > Maybe, but first we need to look at how useful this is in practice. And what > about the reversed case, where a new definition is a generalization of one or > more methods? I agree, maybe it is not useful. Your idea is very interesting, I never even considered that. Can you think of a useful example? > >Another case is specialization by value: > I think this is not useful enough to justify making the type system more > complex. I agree. Would this be a proper description of the (future) method model in Nice?: Every method has exactly one type and zero or more implementations. A method can be specialized by other methods; when this is done, the implementations of all the specializing methods are considered also to be implementations of the specialized method. For a method M to be specialized by a method N, for every nth parameter P(M,n) and P(N,n), it must be true that P(M,n) : T, P(N,n) : U implies U <: T, and if V and W are the return types of M and N, respectively, then W <: T. Methods are dispatched to a particular implementation based on the types and/or values of the actual parameters. This leaves syntactical issues aside, including whether or not M and N have to have the same local name. - Brian ------------------------------------------------------- SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now! http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click