sir-haver
sir-haver

Reputation: 3592

Two ways of creating subclass that are practically the same?

I'm new to Java. I created a super class and a sub-class that extends from it:

class Car {
    private String name;
    private int wheels;

    public Car(String name, int wheels) {
        this.name = name;
        this.wheels = wheels;
    }
}

class Ford extends Car {
    public Ford(String name, int wheels) {
        super(name, wheels);
    }

}

And then in the main method I can create an instance of the super class and of the sub-class:

  Car car = new Car("car", 4);

   Ford ford = new Ford("ford", 6);

   Car ford2 = new Ford("ford", 6);

I just wanted to ask if there is any difference in creating the instance with Ford in the beginning, or Car in the beginning of the sentence? As you can see ford and ford2 are created differently. Please note that I know that ford and ford2 are not the same since they are reference variables with different pointers. I'm only wondering about the syntax with which they are created. Thanks

EDIT:

I foud out the difference but don't understnand the logic behind it.

I don't really understand why, ford2 is still an instance of Ford

Upvotes: 0

Views: 95

Answers (5)

SSP
SSP

Reputation: 2670

   Ford ford = new Ford("ford", 6);

   Car ford2 = new Ford("ford", 6);

Both object variable are referring Ford class object. but type of object variable are different. like ford is type of ford but ford2 is type of car.

Its called generalize object creation. generalize object reference creation is always suggest as you can change there object reference type by assigning different kind of subclass inheriting same super class.

Apart from this below mention difference is also a case which is useful.

Car car = new Car("car", 4);

This car object can only access Car class methods.

Ford ford = new Ford("ford", 6);

This object can access all methods of both class. But suppose you have 1 method like below in both class

   public static void a(){
        system.out.println("static method");
   }

if ford object call method a(). it will run method present in subclass. because ford variable is type of Ford subclass.

 Car ford2 = new Ford("ford", 6);

This object can access all methods of both class. But suppose you have 1 method like below in both class

   public static void a(){
        system.out.println("static method");
   }

if ford object call method a(). it will run method present in superclass. because ford2 variable is type of Ford superclass.

Upvotes: 1

Michael
Michael

Reputation: 44150

I really don't like any of these answers so far. They are making something simple sound complex.

A variable is just a holder for a reference.

As you can see from your examples, the type of the variable does not have to match the exact type of the reference it holds. The variable just has to be equal to or more general (or, if you prefer, equal to or less specific) than its reference. Car is more general than Ford, so that assignment is okay.

Every reference can be held by an Object variable, since that is the most general type which exists in Java.

Object foo = new Car(1, 6);
Object bar = "hello world";

Now, the difficulty with these variables is that we can only call the methods from the Object class. By declaring the variable as Object, when I try to access the contents then I can only use methods from Object no matter what's really stored in there.

There are a couple of methods in Object (like toString) so this may be okay, but in most cases assigning to Object is not very useful.

So, the more specific we are with our variables, the more functionality we potentially get access to.

When you say

Car car = new Ford("ford", 6);

there might be some Ford-specific functionality which we cannot access when referring to it from this variable. We can always get around that later by casting the instance but you should avoid doing so unless absolutely necessary.

However, the more general we are, the more flexible our code becomes. If a method only takes Ford cars as a parameter, that is quite restrictive. If it can take any car as a parameter, it is more flexible.

In general, when choosing the correct type for the variable, you can mentally start off with the most general type that you can, and then keep making it more specific until it fits your use case.

For example, if you can then prefer Iterable over a Collection, prefer Collection over a List, and prefer List over an ArrayList.

Upvotes: 2

scottb
scottb

Reputation: 10084

I just wanted to ask if there is any difference between the instance ford and ford2? Or are they exactly the same?

The best answer is: it depends.

It depends on what, exactly, you mean by "the same."

In Java, the new operator is required to create a new object. Therefore, the two assignments will assign newly created objects to the variables ford and ford2. These objects will have different references and, therefore, different identities in the JVM. As a result, the following will evaluate to false:

boolean b = (ford == ford2);

The two objects, however, can be said to have the same attributes as their instance fields contain the same values. As it stands, this expression would also evaluate to false:

boolean b = (ford.equals(ford2));

because the default equals() method inherited from Object by both the types of the assigned variables (i.e., Car and Ford) performs the same reference comparison as was evaluated in the previous statement. If the equals() method in the Ford class was overridden to perform a value comparison (instead of the default reference comparison) as follows:

@Override boolean equals(Object ob) {
    if (!(ob instanceof Ford)) return false;
    Ford f = (Ford) ob;
    return this.name.equals(f.name) && this.wheels == f.wheels;
}

then the following expression would evaluate to true:

boolean b = ford.equals(ford2);

TL;DR: the objects referenced by the variables ford and ford2 have the same type (i.e. they are both Fords), the same attributes, but different identities. If a value comparison is defined for the class Ford as shown, then they would have the same values, otherwise they would not.

Upvotes: 0

CoderCharmander
CoderCharmander

Reputation: 1910

Technically they are not same - == will give false - but they hold the same data (not same means modifying one will not affect the another) and they are the same type. But, you can only call ford2's methods that are only defined in the Ford class (if there were any) by casting it to Ford (in this state, on ford2 you can only call Car's methods).

Upvotes: 0

arcadeblast77
arcadeblast77

Reputation: 570

You can call any Ford method on ford.

You can call any Car method on ford2.

Upvotes: 0

Related Questions