关于Java中动态类型的问题

时间:2010-01-27 17:57:28

标签: java inheritance

我从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 

}

你能告诉我打印出来的原因和原因吗?教练说B.f,但我不明白为什么。我以为是A.f.谢谢(不,我不在课堂上,只是想学习。)

编辑:对于我从视频讲座中复制的错误感到抱歉。

3 个答案:

答案 0 :(得分:2)

此示例演示了面向对象编程的强大功能。

因为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();
}

我遗漏了各种各样的细节来说明问题:这段代码不会编译。

但是重点在于:推销员有一种不同的方法来计算他们的工资,而不是其他员工:他们是按佣金而不是每小时支付的。 (在现实生活中,我们大概也有受薪员工,但正如我所说,我正在简化。)计算任何类型员工薪酬的功能都是从一个更大的功能中调用,也可以做其他事情。面向对象编程的优点在于我们可以调用外部函数,而不关心我们调用它的对象是普通的Employee还是Salesman。每个对象都知道它是什么,并调用正确的函数。在示例的最后几行中,我们有一些包含常规Employees和Salesmen的结构,我们可以遍历并处理它们而无需检查它们的类型。没有OOP,我们必须不断编写如下代码:“if(type == SALESMAN)... else if(type == HOURLY)...”

答案 1 :(得分:1)

“B.f”打印的原因是因为方法的实现是由对象的运行时类型决定的,而不是它的编译时类型。它就像C ++中的virtual关键字。

构建B后,即使f被称为B,您也知道调用其A方法会打印“Bf”。

此外,您的A.f方法缺少近距离支撑。

答案 2 :(得分:1)

该代码不正确,A.g()不接受任何参数。

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

A.G(X);试图在A上调用一个静态方法,用x作为参数。 对于您发布的代码示例,这是不可能的。

除了错误的代码之外,原因是B用自己的实现覆盖方法f()。 因此B的任何实例,例如B x = new B();将调用B定义的不是A.f()的f()。到达A.f()的唯一方法是通过调用super.f()来自B的实例内部。