Why can you cast to an abstract class
I'm reading a book about data structures in java, and it's talking about iterators now. I saw the following code and it seems odd to me. In the following code, AbstractIterator
is an abstract class that implements Iterator<E>
, UniqueFilter
is a subclass of AbstractIterator
that is not abstract, and data
is a Vector. I guess I don't understand how in the first line you can take the output of the Vector.iterator() method and cast that into an abstract class. After line 1, is dataIterator
not an instanti开发者_JAVA百科ated instance of an abstract class?
AbstractIterator<String> dataIterator =
(AbstractIterator<String>)data.iterator();
AbstractIterator<String> ui = new UniqueFilter(dataIterator);
The problem is that there are two different types we are talking about. The (run time) type of an object and the (compile time) type of a reference.
dataIterator
is a reference of an abstract type - that's ok.data.iterator()
returns a reference to an object whose type is not clear from the example, but apparently it's a concrete type which inherits fromAbstractIterator<String>
- that's ok- You can always assign a reference to object of type B to a reference to object of type A if B is a child of A, even if A is abstract (or interface). You actually don't need the cast.
So after line one dataIterator
is still a reference of type AbstractIterator<String>
, but it's a reference to an object of a concrete type which implements AbstractIterator<String>
.
Remember, in JAVA all the object variables are actually references.
UniqueFilter
is irrelevant for this question, btw.
Inheritance means IS-A. If a Child inherits from a Parent, then Child IS-A Parent and can be used in any situation where a Parent is called for.
Since UniqueFilter
IS-A AbstractIterator
, this means you can cast it just as your code shows.
Why would you not believe the JVM?
After line 1, is dataIterator
not an instantiated instance of an abstract class?
It is an instance of a UniqueFilter
which also makes it an AbstractIterator
by inheritance. Attempting to "instantiate and instance of an abstract class" means attempting to call the abstract class' constructor, that's what's not allowed, and that's what's not happening here.
Abstract Class is a class that cannot be instantiated. Often it will include one or more methods that are also declared abstract and must be implemented by subclasses for the subclass to be concrete (opposite of abstract), and therefore able to be instantiated.
UniqueFilter
is a subclass of AbstractIterator
( an abstract class). Since this is a IS-A
kind of relationship, you cannot declare an instance of abstract class.
If you want to create an instance for abstract class, first you create a concrete subclass and create an instance for that and use it.
From what you've described it looks like there's an assumption that can be made that has been overlooked; that the implementing type returned by data.iterator()
here is a subclass of AbstractIterator<String>
.
If this assumption can be made, then the first statement becomes obvious as an object can be legally type cast to any object up the inheritance hierarchy, in this case an AbstractIterator<String>
.
In this case dataIterator
is NOT an instantiated instance of an abstract class; its not being instantiated here (i.e new AbstractIterator<String(...)
), its just a reference to the instantiated instance returned by Vector.iterator()
with the type being that of a superclass of the actual returned type, which happens to be an abstract class.
HeadofState is an abstract (by the English meaning of the word abstract) term.
There is no country in the world where the official title of its head-of-state is Head-of-State.
A head-of-state, even though abstract in language and existence, is a super class or super category of titles like sultan, president, premier, prime minister, beloved father, etc.
So, even though the existence of head-of-state cannot be instantiated in its abstract form, you can instantiate (by democratic means, hereditary or by coup) a president, a prime minister, or any honcho-what-nots.
So say, a prime minister has been instantiated, it can then be equated to its abstract parent terminology of "Head-of-State".
So even though an abstract class cannot be instantiated, an implementation of that abstract class can be instantiated. That is what factories can do. Factories are a means to create instances of abstract classes.
Just like abstract classes, interfaces cannot be instantiated but must be implemented. Abstract classes are partially implemented, whereas interfaces are totally unimplemented by themselves. Abstract classes and interfaces depends on derivative classes to complete their existence. Of course, the obsessive OO-purist's technical terminology would clarify that abstract classes are "extended" and interfaces are "inherited".
For example, HttpServletRequest is an interface. You cannot instanstiate it directly. When your JSP grabs its http servlet request, it works the same whether you are in Jetty or Tomcat. However, if you inspect carefully, the actual class instantiated by the HttpServletRequest factory in Jetty is different from that created in Tomcat. But, since both of them implement HttpServletRequest, those instances can simply be equated to a variable whose type is HttpServletRequest.
You should read up on abstract classes vs interfaces and how interfaces are concocted to allow pseudo-multiple inheritance in Java. Once you understand the role of interfaces, you would then understand abstract classes. In the realm of object-oriented flame wars, some people think that Interfaces was a brilliant break-thro in multiple inheritance. Some people think interfaces have nothing to do with multiple inheritances. In my own less than humble opinion, interfaces are a poor and failed attempt at socialist's paternalistic indulgence to prevent me from getting into trouble that presumes that I don't know how to take care of myself.
精彩评论