ftp.nice.ch/peanuts/GeneralData/Usenet/news/1989/CSN-89.tar.gz#/comp-sys-next/1989/Jul/Deferred-methods-and-strong-typing

This is Deferred-methods-and-strong-typing in view mode; [Up]


Date: Sun 05-Jul-1989 08:41:34 From: Unknown Subject: Deferred methods and strong typing Consider a class that has a deferred method: A.h: #import <objc/Object.h> @interface A:Object {...} - (A*)someMethod; ... @end A.m: #import "A.h" - (A*)someMethod { return [self subclassResponsibility]; } and a subclass that implements that method: B.h: #import "A.h" @interface B:A {...} - (B*)someMethod; ... @end B.m: #import "B.h" - (B*)someMethod { ... actual implementation ... } Now, consider the use of someMethod: C.m: #import "B.h" ... [anInstanceOfB someMethod]; Intuition tells me that B's someMethod is to be used. But the compiler in 0.9 gives a "multiple declarations for method `someMethod'" warning, and then uses A's someMethod. What's the scoop?
Date: Sun 06-Jul-1989 18:48:42 From: Unknown Subject: Re: Deferred methods and strong typing >From the article with Jacob Gore's question about the "multiple declarations for method `someMethod`" warning, consider the two .h interface files: A.h #import ... @interface A : Object .. -(A *)someMethod; @end B.h #import "A.h" @interface B : A ... -(B *)someMethod; @end Then usage in C.m #import "B.h" ... [anInstanceOfB someMethod]; One piece of information missing is the declaration of 'anInstanceOfB'. The warning will be given by the compiler if 'anInstanceOfB' is declared type 'id'. This is because the compiler sees both interface files and the fact the programmer has deferred binding until runtime (type id). The compiler then choses the first interface as the default (notice the order of @interface statements based on "#import" ordering). Correct type information can be given to the compiler by: 1) Typing the method: [(B *)anInstanceOfB someMethod]; 2) Declaring anInstanceOfB to be type B: B *anInstanceOfB; Hope this helps. Andy Novobilski andyn@stepstone.com The Stepstone Corp. (The Objective-C People) 75 Glen Rd. Sandy Hook, CT 06770 (203)426-1875 >From: dml@esl.UUCP (Denis Lynch)
Date: Sun 06-Jul-1989 21:30:45 From: Unknown Subject: Re: Deferred methods and strong typing In article <130007@gore.com> jacob@gore.com (Jacob Gore) writes: >Consider a class that has a deferred method: > A.h: > #import <objc/Object.h> > @interface A:Object {...} > - (A*)someMethod; >and a subclass that implements that method: > B.h: > #import "A.h" > @interface B:A {...} > - (B*)someMethod; >Now, consider the use of someMethod: > C.m: > #import "B.h" > [anInstanceOfB someMethod]; > >the compiler in >0.9 gives a "multiple declarations for method `someMethod'" warning, and >then uses A's someMethod. > >What's the scoop? The problem is philosophically thorny, but solving it is easy. Remember that Objective C insists on one system-wide template for each message selector. That is, if one class has a method (int)lifeTime then all lifeTime messages must return (int). Your example has introduced two definitions for someMethod: one says it will return (A*) and one says (B*). This violates Objective C's ground rules. Philosophically your example makes sense, since indeed all Bs are As, so B's definition of someMethod is consistent with A's, just more specific. It would seem that Objective C doesn't analyse this case as carefully as you did, so it missed the subtlety. You shouldn't have any trouble if you just change the defintion of B's someMethod to (A*). Returning a B will be legal (since Bs are As), and the Objective C method definition things won't get in the way. Good luck!
Date: Sun 07-Jul-1989 07:42:52 From: Unknown Subject: Re: Deferred methods and strong typing / comp.sys.next / andyn@stpstn.UUCP (Andy Novobilski) / Jul 6, 1989 / > One piece of information missing is the declaration of 'anInstanceOfB'. > The warning will be given by the compiler if 'anInstanceOfB' is declared > type 'id'. This is because the compiler sees both interface files and > the fact the programmer has deferred binding until runtime (type id). The > compiler then choses the first interface as the default (notice the order > of @interface statements based on "#import" ordering). > > Correct type information can be given to the compiler by: This is the one I used: > 2) Declaring anInstanceOfB to be type B: > B *anInstanceOfB; That is where the error happened. I don't think the compiler should have chosen the 'someMethod' declared in class A over the one declared in class B. If I left 'someMethod' as type id in both the subclass (B) and the superclass (A), the subclass's method would overrule the superclass's method of the same name (the essense of Objective C's method inheritance mechanism, right?). However, once type information is provided for the subclass and the superclass, the compiler decides that they are not the same method at all, and proceeds to choose the first one it encounters, which, by convention (since a subclass imports its superclass's interface), is the superclass's method. Not nice. > 1) Typing the method: > [(B *)anInstanceOfB someMethod]; This should not be necessary. Strong typing should not break the inheritance chain. For now, I declare 'someMethod' in class B as returning (A*) instead of (B*), but hey... something is wrong here!
Date: Sun 07-Jul-1989 07:42:52 From: Unknown Subject: Re: Deferred methods and strong typing / comp.sys.next / andyn@stpstn.UUCP (Andy Novobilski) / Jul 6, 1989 / > One piece of information missing is the declaration of 'anInstanceOfB'. > The warning will be given by the compiler if 'anInstanceOfB' is declared > type 'id'. This is because the compiler sees both interface files and > the fact the programmer has deferred binding until runtime (type id). The > compiler then choses the first interface as the default (notice the order > of @interface statements based on "#import" ordering). > > Correct type information can be given to the compiler by: This is the one I used: > 2) Declaring anInstanceOfB to be type B: > B *anInstanceOfB; That is where the error happened. I don't think the compiler should have chosen the 'someMethod' declared in class A over the one declared in class B. If I left 'someMethod' as type id in both the subclass (B) and the superclass (A), the subclass's method would overrule the superclass's method of the same name (the essense of Objective C's method inheritance mechanism, right?). However, once type information is provided for the subclass and the superclass, the compiler decides that they are not the same method at all, and proceeds to choose the first one it encounters, which, by convention (since a subclass imports its superclass's interface), is the superclass's method. Not nice. > 1) Typing the method: > [(B *)anInstanceOfB someMethod]; This should not be necessary. Strong typing should not break the inheritance chain. For now, I declare 'someMethod' in class B as returning (A*) instead of (B*), but hey... something is wrong here!
Date: Sun 08-Jul-1989 03:21:15 From: Unknown Subject: Re: Deferred methods and strong typing In article <3312@stpstn.UUCP> andyn@stepstone.com (Andy Novobilski) writes: > >Correct type information can be given to the compiler by: > >1) Typing the method: > [(B *)anInstanceOfB someMethod]; > >2) Declaring anInstanceOfB to be type B: > B *anInstanceOfB; Isn't it true that the warning is generated because of the *declaration* of someMethod, not its use? (Of course the run-time problem happens because of the use). This seems to be pretty much required because of the *possibility* of dynamic binding: the compiler needs to be able to figure out what someMethod will return under any circumstances, especially since common usage is to type everything as id. (I know I could go try this on my machine, but it's in another room...) This seems to be one of the prices to be paid for using dynamic binding in a language that doesn't fully support it. In Smalltalk there is no such problem, since someMethod will return whatever it wants. In C we don't have that luxury.
Date: Sun 09-Jul-1989 07:42:18 From: Unknown Subject: Re: Deferred methods and strong typing / comp.sys.next / dml@esl.UUCP (Denis Lynch) / Jul 7, 1989 / > Isn't it true that the warning is generated because of the *declaration* of > someMethod, not its use? (Of course the run-time problem happens because of > the use). Yes, but the two problems are related: because (B*) is not recognized as a subtype of (A*), the method in class B is treated as an alternative to the one in class A, instead of being treated as its replacement (for instances of B and of its subclasses). > This seems to be pretty much required because of the *possibility* of > dynamic binding: the compiler needs to be able to figure out what someMethod > will return under any circumstances, especially since common usage is to > type everything as id. But subtyping is implemented correctly in at least some cases. For example, you can do: @implementation B:A ... (A*)someMethod { ... return self; } Even though the return value is of type (B*), it is (correctly) understood to match the declared return type, (A*). So it doesn't look like a language problem (I was worried for a while that the concept of subtyping was omitted altogether, and was quite relieved to find out otherwise), but just a compiler bug. Does the Stepstone compiler exhibit the same problem, or is it limited to the 0.9 version of NeXT's compiler? (If I understand the docs correctly, they are no longer the same beast.)

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Marcel Waldvogel and Netfuture.ch.