Now that we've talked about abstract classes, let's revisit the difference between an object and a reference, between a type and a class. And so when we have some code like this, Car mySportsCar = new SportsCar(), let's relabel what these things are. Car is not the class, Car is the type, okay? And I want to always make it clear the difference between a type and a class. Classes can be used as types but the difference is this, mySportsCar is not an object. It is a primitive. It is a reference. And the type of that reference is Car. Where's the object? There isn't one until we say new and provide it with the constructor. new goes off and creates a new object in the heap, invokes the constructor and returns that object's reference. Think of it as its address logically. And that's what we're storing in mySportsCar. Now mySportsCar is a reference, it does not know what the actual class is, what the actual implementation is. It only knows what type it's been declared of, very simple rule. Whatever the implementation is, whatever the class is, in this case SportsCar, we must be able to say class is a type, SportsCar is a Car. And that's going to be true whether we're talking about classes or later on in the next unit when we talk about interfaces. We want to be able to use that is a concept in terms of inheritance. So even though the implementation is SportsCar, the reference only knows about the things that its type declares. So it would only know about what belongs to Car. Now if Car is a class, we can talk about attributes, we can talk about methods. In general, once again, we don't ever want to talk about attributes, or as the Java internals actually calls them, fields. We want to be talking about methods, about code. So even though the implementation of mySportsCar is a mySportsCar, the only thing we can actually access is what Car says we can do. And we can look at this very concretely in our example. Here we are in CarApp. And I've gone ahead into SportsCar and added the race method. And when you say race, it will set speed to whatever the maximum speed is. So here in CarApp, just as a temporary measure, I have put in the following, all right? Here's our thing Type and then the reference, that's what we call the variable, equals the new Class, the new implementation. So here we see SportsCar sc = new SportsCar. So sc is a reference to this SportsCar object. But here Car c, c is a reference and it's also being assigned to the same value. If we were to look at and do an equals sc = c, they're exactly the same reference. They're pointing at exactly the same object, the same implementation. But look at the difference. I can say sc race, because sc is of type SportsCar. But I cannot say c.race, because race is not defined for type Car. Even though c under the covers actually is a SportsCar, we can only see what the reference's type allows us to see, what it declares. This is a very, very important concept in object-oriented programming, especially in a language like Java. So that's why we can't say mySportsCar.race. Because the type is Car even though the implementation would know what to do with it. So yes, this is talking about polymorphism. Because whenever we have the is a relationship, we can be talking about polymorphism. And in fact, in Java you cannot have polymorphism outside of the is a relationship. They have to be related in some manner, using inheritance in Java to make that work. But the way we'll do that in Java is by declaring interfaces. and we can still use is a there. And so as long as two otherwise unrelated classes implemented the same interface, we can use is a. And therefore, they are polymorphic through that interface. In Java, to have polymorphism, we must have inheritance. But that can be in the case of interface, not just classes, which is what we've been working with so far. I can have as we've had in our sample app, a whole group or collection or in this case array of otherwise unrelated objects. I mean, car 54 is currently a SportsCar because Car now is abstract and we couldn't create it. Moch5 is a SportsCar, wagon is a station wagon, SUV is an SUV Class. They're all of different classes, but they all have a common is a relationship at Car. So as long as we talk about them all as Car, we can group them together. But we can only talk about them commonly there. I can't go through here and tell them to race, can't do that, because race is not known to the Car type. So there is that error again. Race is not defined on Car. And that prevents us from making mistakes because, in this case, only two out of the four things would know how to race. And we can talk about the attributes when we're talking about classes. But again, we shouldn't really ever talk about attributes, because attributes are data and data should be private. We could talk about properties, which are the result of calling methods. But we shouldn't be talking about attributes in any sort of polymorphic manner, because now you're talking about data across classes. The data's private, you shouldn't have access to anybody's private data. So in this code, we've declared a reference type that is argument aCar is not a Car, it's a Car reference. So the type of the reference is Car, and so anything that extends Car is a valid thing. Anything where I have that is a relationship would be valid. SportsCar is a Car, Cargo is a Car, SUV is a Car, StationWagon is a Car. Anything that is a Car, we can take polymorphically and invoke setSpeed because setSpeed is coming from the Car class.