Java: разница между A x = new A () и A x = new B (), когда B расширяет A

Возможный дубликат:
java наследование – пожалуйста, объясните

Я изучаю Java, и у меня есть два вопроса:

  1. В чем разница между:

    A x = new A(); 

    а также

     A x = new B(); 

    Учитывая, что:

     class A class B extends A 
  2. В чем разница между:

     A x = new B(); (A)x.run_function(); 

    Предположим, что оба A и B имеют функцию run_function , какая из них будет выполнена?

Важнейшее различие между статическими и динамическими типами объектов и ссылками на объекты.

Скажем, B продолжается A и C расширяет B.

Динамический тип объекта (тип, используемый в новом) – это его фактический тип времени выполнения: он определяет фактические методы, которые присутствуют для объекта.

Статический тип ссылки на объект (переменная) является типом времени компиляции: он определяет или, скорее, объявляет, какие методы можно вызывать на объекте, который ссылается на переменную.

Статический тип переменной всегда должен быть одного типа или супертипа динамического типа объекта, который он ссылается.

Таким образом, в нашем примере переменная со статическим типом A может ссылаться на объекты с динамическими типами A, B и C. Переменная со статическим типом B может ссылаться на объекты с динамическими типами B и C. Переменная со статическим типом C может ссылаться только на объекты с динамический тип C.

Наконец, вызов метода по ссылке на объект – это тонкое и сложное взаимодействие между статическими и динамическими типами. (Прочтите спецификацию языка Java при вызове метода, если вы мне не верите.)

Если оба A и B реализуют метод f (), например, а статический тип – A, а связанный с ним динамический тип – это C для вызова метода, то Bf () будет вызываться:

 B extends A, C extends B public Af() {} public Bf() {} A x = new C(); // static type A, dynamic type C xf(); // Bf() invoked 

Упрощение упрощения: сначала статические типы как приемника (типа A), так и аргументы (без аргументов) используются для определения наиболее подходящей (наиболее конкретной) сигнатуры метода для этого конкретного вызова, и это делается во время компиляции. Здесь это, очевидно, Af ().

Затем на втором этапе во время выполнения динамический тип используется для определения фактической реализации нашей сигнатуры метода. Начнем с типа C, но мы не найдем реализацию f (), поэтому переходим к B, и там мы имеем метод Bf (), который соответствует сигнатуре Af (). Таким образом вызывается Bf ().

В нашем примере мы говорим, что метод Bf () переопределяет метод Af (). Механизм переопределения методов в иерархии типов называется подтиповым polymorphismом.

1. В

 A x = new A(); 

x является экземпляром A и типа A

тогда как в

 A x = new B(); 

x является экземпляром B и типа A


2. Важно отметить, что (во втором случае), если вы вызываете x.someMethod() , будет вызываться метод B , а не метод A (это называется динамической привязкой , в отличие от статической привязки ). Кроме того, литье меняет только тип , поэтому

 A x = new B(); ((A)x).run_function(); // Need extra parenthesis! 

будет по-прежнему вызывать метод B


Как я сказал выше, вам нужно включить эти дополнительные скобки, поскольку

 (A)x.run_function(); 

эквивалентно

 (A)(x.run_function()); 

Дело 1:

Вы увидите разницу, когда у вас есть метод в B, который НЕ находится в A.

Когда вы пытаетесь вызвать этот метод с использованием ссылки «x», он не будет виден.

Случай 2:

Все вызовы методов будут основаны на типе объекта не ссылочного типа из-за polymorphismа (кроме статических методов)

 A x = new B(); 

В этом случае будет run_function class B run_function .

 A x = new A(); 

В этом случае будет выполняться class run_function .

 1.What is the difference between: A x = new A();and A x = new B(); 

Разница в том, что в первом случае вы создаете экземпляр classа типа A. Таким образом, вы сможете только вызывать методы, определенные в A. Во втором случае, если один и тот же метод имен существует как в A, так и в B, тогда B будет вызываться во время выполнения.

Однако во втором случае, используя reflection, также можно будет вызывать методы, которые определены в classе B, а не в classе A.

A x = new B(); (A)x.run_function(); Предположим, что оба A и B имеют функцию run_function, какая из них будет выполнена?

Помните – переопределение определяется во время выполнения, тогда как перегрузка определяется во время компиляции.

Таким образом, метод в classе B будет вызываться во время выполнения на основе Dynamic Binding.

  1. Нет никакой реальной разницы. Фактически для второго случая A старит объект B, но B является A, поэтому нет проблем. B в этом случае ведет себя как A.

  2. Он будет вызывать функцию run_function ()

Кроме того, с:

 A x = new B() 

Вы не сможете выполнять методы, определенные в B и которые не определены в A Однако, как указано ранее из-за polymorphismа в Java, если вы выполняете какие-либо методы, а B' переопределил эти методы, то он будет использовать реализацию B

  • Почему мой открытый class не может расширить внутренний class?
  • Каковы правила, определяющие наследование статических переменных в Java?
  • Нельзя наследовать от std :: vector
  • Наследование диаманта (C ++)
  • Когда использовать собственное наследование C ++ над составом?
  • Наследование backbone.js
  • Перегрузка и переопределение
  • Почему в Java нет множественного наследования, но допускается реализация нескольких интерфейсов?
  • Как сделать моделирование наследования в реляционных базах данных?
  • Может ли интерфейс расширять несколько интерфейсов в Java?
  • Абстрактные функции в языке Swift
  • Давайте будем гением компьютера.