Re: A question about static typing
Re: A question about static typing
- Subject: Re: A question about static typing
- From: "Dennis C. De Mars" <email@hidden>
- Date: Sun, 22 Jul 2001 10:32:21 -0700
on 7/22/01 8:40 AM, Chris Gehlker at email@hidden wrote:
>
On 7/21/01 10:30 AM, "Greg Titus" <email@hidden> wrote:
>
>
> But to get back to the main point: yes, using static typing whenever you
>
> know what kind of object you are expecting is good practice because then
>
> you do get those compiler warnings that _usually_ mean you've done
>
> something wrong.
>
>
Thanks Tony & Greg,
>
>
I think it's just a flaw in the book that they don't follow their own advice
>
and static type whenever possible. I've been reviewing it and come across
>
examples like refreshCalendar that starts out:
>
>
NSCalendarDate *firstOfMonth *selDate
>
...
>
id cell
>
>
That made me ask "Why not 'NSButtonCell *cell'?"
>
>
But then looking at other functions, it is "NSButtonCell *aCell" so I guess
>
they just missed a few. One place they seem consistent, though, is in using
>
id for the return type of initializers. Is this a convention?
Yes, that's a convention. This is an example of why, when I see an "id"
declaration, I can never be 100% sure it wasn't done on purpose, because
sometimes there is a reason not to use static typing.
I believe the main reason init methods return id is in case you want to
override it in a subclass. For instance, if you had a class "Vegetable" and
a subclass "Carrot" and defined the init method for Vegetable:
Vegetable* veggie = [[Vegetable alloc] init];
Well, if "init" was declared to return Vegetable* then it also would have to
return the same type in the overridden method. That wouldn't interfere with
the actual definition of the method since it would return a Carrot* which is
a Vegetable*, but then if you wanted to actually assign the results of the
init to a variable as in:
Carrot* myCarrot = [[Carrot alloc] init];
...you'd get a compiler warning because you were assigning the results of
init, a Vegetable*, to a Carrot*.
Actually, init is a method of NSObject, so if the result of init wasn't id
it would pretty much have to be NSObject*, so you'd get a compiler warning
for almost any practical use of init. Same applies to variations of init
that take arguments, you could assign to variables of the same type as the
class where the init variation was first defined, but you'd get a warning
for every subclass that used the same init variation.
So, init and brethren pretty much have to return "id," otherwise you'd get
so many compiler warnings it would make the warning system useless. (And
this isn't even the only issue, there are similar issues related to sending
init to the superclass in the overriding method).
There are some other examples in Cocoa, in the collection classes for
instance, where "id" is deliberately used to avoid these kinds of issues
with subclasses. This tends to happen in places where objects return other
objects of the same class as themselves.
A couple of months ago I was trying to think of ways Obj-C could be modified
to reduce the use of id and make typing possible in more circumstances (I
would especially like strong-typed collections) and I even thought I was
onto some ideas that could be added to the language without disrupting the
way things are currently done, but I eventually ran into issues similar to
what I just outlined above. My current feeling is that the current static
typing scheme adds about as much tying as can be added to Obj-C without
fundamentally changing the language. I would welcome any further
improvements in this area, but for now I've decided it's not worthwhile to
fight the basic dynamic nature of Obj-C.
- Dennis D.