Два способа создания подкласса, которые практически одинаковы? - PullRequest
0 голосов
/ 20 сентября 2019

Я новичок в Java.Я создал супер класс и подкласс, который выходит из него:

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);
    }

}

И затем в методе main я могу создать экземпляр суперкласса и подкласса:

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

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

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

Я просто хотел спросить, есть ли разница в создании экземпляра с Ford в начале или с Car в начале предложения?Как видите, ford и ford2 созданы по-разному.Обратите внимание, что я знаю, что ford и ford2 - это не одно и то же, поскольку они являются ссылочными переменными с разными указателями.Меня интересует только синтаксис, с помощью которого они создаются.Спасибо

РЕДАКТИРОВАТЬ:

Я понимаю разницу, но не понимаю и логики, стоящей за ним.

  • Если у вас есть метод в классе Car, выможет вызывать его как из ford, так и из ford2
  • . Если у вас есть метод с одинаковым именем в классах Car и Ford, вы можете вызвать его как из ford, так и из ford2, и он вызовет метод в подпрограмме.class
  • Если у вас есть метод только в классе Ford, вы НЕ МОЖЕТЕ вызывать его из ford2 - вы получите ошибку.

Я не совсем понимаю, почему ford2еще экземпляр форда

Ответы [ 5 ]

2 голосов
/ 20 сентября 2019

Мне действительно пока не нравятся эти ответы.Они делают что-то простое, звучащее сложным.

Переменная - это просто держатель для ссылки.

Как видно из ваших примеров, тип переменной не обязательно должен соответствовать точномутип ссылки, которую он содержит.Переменная должна быть равной или более общей (или, если хотите, равной или менее конкретной ), чем ее ссылка.Car является более общим, чем Ford, так что присвоение в порядке.

Каждая ссылка может храниться в переменной Object, поскольку это самый общий тип , который существуетв Java.

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

Теперь, проблема с этими переменными состоит в том, что мы можем вызывать методы только из класса Object.Объявляя переменную как Object, когда я пытаюсь получить доступ к содержимому, я могу использовать только методы из Object независимо от того, что там действительно хранится.

В Object есть несколько методов (например, toString), так что это может быть хорошо, но в большинстве случаев присвоение Object не очень полезно.

Итак,чем конкретнее мы обращаемся к нашим переменным, тем больше функциональности мы потенциально получаем к доступу.

Когда вы говорите

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

, могут существовать некоторые специфические для Ford функции, к которым мы не можем обратиться при обращениик нему из этой переменной.Мы всегда можем обойти это позже, приведя экземпляр, но вам следует избегать этого, если это абсолютно не необходимо.

Однако, чем более мы общие, тем более гибким становится наш код.Если метод принимает в качестве параметра только автомобили Ford, это довольно ограничительно.Если в качестве параметра можно использовать любой автомобиль, он более гибкий.

В общем, при выборе правильного типа для переменной вы можете мысленно начать с самого общего типа, который вы можете, и затем сохранитьсделав его более конкретным, пока он не будет соответствовать вашему варианту использования.

Например, если вы затем можете предпочесть Iterable над Collection, предпочитаете Collection над List и предпочитаете List надArrayList.

1 голос
/ 20 сентября 2019
   Ford ford = new Ford("ford", 6);

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

Обе переменные объекта ссылаются на объект класса Ford.но тип переменной объекта другой.Например, ford - это тип ford, но ford2 - это тип автомобиля.

Это называется генерацией создания объекта.Обобщение создания ссылки на объект всегда предлагается, поскольку вы можете изменить там тип ссылки на объект, назначив различный вид подкласса, наследующего один и тот же суперкласс.

Помимо упомянутого ниже различия также есть случай, который полезен.

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

Этот автомобильный объект может получить доступ только к методам класса Car.

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

Этот объект может получить доступ ко всем методам обоих классов.Но предположим, что у вас есть 1 метод, как показано ниже, в обоих классах

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

, если ford объект вызывает метод a ().он будет запускать метод, представленный в подклассе.потому что переменная ford является типом подкласса Ford.

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

Этот объект может получить доступ ко всем методам обоих классов.Но предположим, что у вас есть 1 метод, как показано ниже, в обоих классах

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

, если ford объект вызывает метод a ().он будет запускать метод, присутствующий в суперклассе.потому что переменная ford2 является типом суперкласса Ford.

0 голосов
/ 20 сентября 2019

Я просто хотел спросить, есть ли разница между экземпляром ford и ford2?Или они точно такие же?

Лучший ответ: это зависит .

Это зависит от того, что именно вы подразумеваете под "одним и тем же"."

В Java оператор new необходим для создания нового объекта.Следовательно, эти два назначения будут назначать вновь созданные объекты переменным ford и ford2.Эти объекты будут иметь разные ссылки и, следовательно, разные идентификационные данные в JVM.В результате следующее будет false:

boolean b = (ford == ford2);

Однако можно сказать, что два объекта имеют одинаковые атрибуты, поскольку их поля экземпляров содержат одинаковые значения.В его нынешнем виде это выражение также оценивается как false:

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

, поскольку метод equals() по умолчанию, унаследованный от Object обоими типами назначенных переменных (т. Е. Car иFord) выполняет такое же эталонное сравнение, как и в предыдущем выражении.Если метод equals() в классе Ford был переопределен для выполнения сравнения значений (вместо эталонного сравнения по умолчанию) следующим образом:

@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;
}

, тогда следующее выражение будетоценивается как true:

boolean b = ford.equals(ford2);

TL; DR: объекты, на которые ссылаются переменные ford и ford2, имеют одинаковый тип (т. е. оба они Ford с), одинаковые атрибуты, но разные тождества.Если сравнение значений определено для класса Ford, как показано, тогда они будут иметь те же значения, в противном случае они не будут.

0 голосов
/ 20 сентября 2019

Технически они не одинаковы - == даст false - но они содержат одинаковые данные ( не одно и то же означает, что изменение одного не повлияет на другое), и они одного типа.Но вы можете вызывать только методы ford2, которые определены только в классе Ford (если они были), приводя его к Ford (в этом состоянии на ford2 вы можете вызывать только Car методы).

0 голосов
/ 20 сентября 2019

Вы можете вызвать любой метод Ford для ford.

Вы можете вызвать любой метод Car для ford2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...