Вопрос о динамической типизации в Java - PullRequest
3 голосов
/ 27 января 2010

Я получил это из веб-трансляции структур данных Berkley CS:

class A {
  void f() {System.out.println("A.f");}
  void g() {f();}
 // static void g(A y) {y.f();}
}

class B extends A {
  void f(){
    System.out.println("B.f");
  }
}

class C {
  static void main (String[] args){
    B aB = new B();
    h (aB);
  }

  static void h (A x) {x.g();}
  //static void h (A x) {A.g(x);}  what if this were h 

}

Можете ли вы сказать мне, что печатает и почему? Инструктор сказал Б.Ф., но я не понимаю, почему. Я думал, что это А.ф. Спасибо (нет, я не в классе, просто пытаюсь учиться.)

редактировать: извините за ошибки, я скопировал его из видео лекции.

Ответы [ 3 ]

2 голосов
/ 27 января 2010

Этот пример демонстрирует мощь объектно-ориентированного программирования.

Поскольку ab является экземпляром B, любой вызов метода для ab будет использовать функции, определенные в B, , даже если эти функции вызываются косвенно через функцию, определенную в суперклассе .

Пример настолько абстрактен, что достоинства этого могут быть неясны. Позвольте мне привести чуть более реалистичный пример:

class Employee
{
  ... bunch of stuff ...
  void calcPay()
  {
    pay=hoursWorked*hourlyRate;
  }
  void produceCheck))
  {
    calcPay();
    calcTaxes();
    calcBenefitDeductions();
    printCheck();
  }
}
class Salesman extends Employee
{
  void calcPay()
  {
    pay=sales*commissionRate;
  }
}
... somewhere else ...
for (Employee employee1 : employeeList)
{
  employee1.produceCheck();
}

Я опускаю все виды деталей, чтобы подчеркнуть: этот код не будет компилироваться.

Но вот в чем суть: у продавца есть другой метод расчета зарплаты, чем у других сотрудников: им платят комиссионные, а не почасовые. (В реальной жизни у нас, по-видимому, также есть наемные работники, но, как я уже сказал, я упрощаю.) Функция для расчета заработной платы любого типа сотрудника вызывается из более крупной функции, которая также выполняет другие функции. Прелесть объектно-ориентированного программирования в том, что мы можем вызывать внешнюю функцию и не заботиться о том, является ли объект, против которого мы ее вызываем, обычным сотрудником или продавцом. Каждый объект знает, что это такое, и вызывает правильную функцию. В последних нескольких строках примера у нас есть некоторая структура, которая включает в себя как обычных сотрудников, так и продавцов, и мы можем проходить и обрабатывать их все без необходимости проверять их тип. Без ООП нам пришлось бы постоянно писать код вроде: "if (type == SALESMAN) ... иначе if (type == HOURLY) ..."

1 голос
/ 27 января 2010

этот код неверен, A.g () не принимает аргументов.

static void h (A x) {A.g(x);}

A.g (х); пытается вызвать статический метод на A с именем g с аргументом x. Это невозможно с примером кода, который вы опубликовали.

кроме неправильного кода, причина в том, что B переопределяет метод f () с его собственной реализацией. Таким образом, любые экземпляры B, такие как B x = new B (); вызовет f (), который B определяет не A.f (). Единственный способ достичь A.f () - это вызвать экземпляр B, вызвав super.f ();

1 голос
/ 27 января 2010

Причина, по которой печатается "B.f", заключается в том, что реализация метода определяется типом времени выполнения объекта, а не его типом времени компиляции. Это как ключевое слово virtual в C ++.

Когда вы создаете B, вы знаете, что при вызове его метода f будет напечатано "B.f", даже если B называется A.

Кроме того, в вашем методе A.f отсутствует закрывающая скобка.

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