With primitives and their Wrappers I understood the concept of Widening. But with respect to other Objects I am getting confused with Widening and implicit Casting. As example
Class Animal{
}
Class Dog extends Animal{
public static void main(args String[])开发者_Python百科{
Dog d = new Dog();
d.go(d);
}
void go(Animal a){ }
}
Edit: the question is which one is preferred widening or casting and why?
(In my opinion) if the casting isn't required then don't do it. Your code will be more readable.
In particular, the syntax:
d.go(d);
is more concise, and just as correct as
d.go((Animal)d);
Basically, take advantage of the widening for reasons I describe below in my first attempt to answer your question.
Well, it depends on what you want the code to accomplish.
If you want a function that can deal with any kind of Animal, Dogs or otherwise, then you should take as input an Animal.
If you want a function that requires something that only Dogs have, or that only makes sense as an operation that takes Dogs as input, then you should take as input a Dog.
edit: perhaps a more contrived example will illustrate why this isn't a question with a straightforward uinversal answer. In Java all objects are children of Object, and as such, any method can be written such that it takes a parameter Object foo
.
Sometimes this can be useful, but its use cases are really quite restrictive, you're limited to the defined methods on Object
.
Suppose instead that you know about Dog
, which is also an Object
. Rather than passing an instance of Dog
as an Object
you might want to get some property specific to Dog
. Basically, if you need to ensure that the argument to some function conforms to some contract, you should restrict the argument to types that conform -- slightly differently: if you need to know that it's a Dog declare it to be a Dog.
As a general rule, you should (in my opinion) choose the "widest" type that conforms to whatever contract you need to fulfill. If you need to know that it's an Animal declare it to be an Animal.
I agree with Mark in saying that it depends. I use a rule of thumb which basically just says that casts of declared types to a subtype are "bad". So if somewhere in your method
void go(Animal a){ ... }
you need a cast like
Dog d = (Dog) a;
you should definitely (if possible) change the parameter a of type Animal to a parameter of type Dog. If the method works on all subtypes of Animal
without a cast then leave it as it is.
精彩评论