您的位置:首页 > Web前端

关于继承的方法和变量

2007-01-06 19:44 369 查看
有些东西真是一天不想就忘了,前段时间看了关于继承的方法和变量的调用,是调用的子类方法,还是调用父类的方法,感觉搞明白了,今天突然想起来,竟然发现给忘记了,呵呵,所以把它记下来,以便再忘了的时候,可以找出来看看。

 class FatClass{
 int var = 1;
 
 public void methodA(){
  System.out.println("A");
 }
 
 public static void methodB(){
  System.out.println("SA");
 }
}

class SubClass extends FatClass{
 int var = 2;
 
 public void methodA(){
  System.out.println("B");
 }
 
 public static void methodB(){
  System.out.println("SB");
 }
}

public class Test{
 public static void main(String[] args){
  FatClass test = new SubClass();
  System.out.println(test.var);
  test.methodA();
  test.methodB();  
 }  
}

其实主要就是关于上面程序的思考。写了一个父类一个子类。父类中写了两个方法和一个变量,子类覆盖了父类的方法和变量。当在程序中声明一个父类的引用,创建一个子类的实例的时候,调用的是父类的方法还是子类的方法,调用的是父类的变量,还是子类的变量的问题。

这里牵掣到了隐藏的概念,也就是说如果定义的是父类引用,实例的也是父类的引用,或者定义的是子类的引用,实现的也是子类的引用,那么无可厚非,定义的是谁,调用的就是谁的方法和变量,但是如果定义的是父类的引用,实现的却是子类,那么在遇到实例方法的时候,实例的是哪个类,就调用那个类的方法,比如这里,test调用methodA的时候,就打印出B字母。父类实例方法被隐藏了。但是调用静态方法methodB的时候,无论实例的是哪个类,都会调用父类的方法,也就是说这里会打印出SA,我是这样理解的,因为静态方法独立于实例存在,也就是说当我们在定义引用的时候FatClass test的时候,静态方法static methodB就已经存在了,这时候就算子类覆盖了方法,但是虚拟机在看到是父类引用类型的时候,就直接找到了那个已经存在了的父类的静态方法,就没有去实例子类的静态方法。

所以以上程序运行结果是

1

B

SA

就可以理解了。

下面是一则关于这个问题的FAQ:

Q. Base b = new SubBase(); How the compiler/Runtime to resolve the addresses of methods calls, Fields?
// TestBinding.java
class Base {
    String s = "string in Base";
    void amethod(){
        System.out.println("amethod() call in Base");
    }
}
class SubBase extends Base{
    String s = "string in SubBase";
    void amethod(){
        System.out.println("amethod() call in SubBase");
    }
}
public class TestBinding {
    public static void main(String[] args) {
        Base b = new SubBase();
        // static binding on instance fields
        System.out.println(b.s); //string in Base
        // dynamic binding on instance methods
        b.amethod(); //amethod() call in SubBase
    }
}
A:
    The above example plus comments actually told everything you need to know.
    When a variable of an object is accessed using a reference, it is the type of the reference, not the class of the current object denoted by the reference, that determines which variable will actually be accessed.
Static Binding -- Bind at compile time : The addressing of the variable is determined at compile time.
    When a method is invoked on an object using a reference, it is the class of the current object denoted by the reference, not the type of the reference, that determines which method implementation will be executed.
Dynamic Binding -- Bind at run time: The addressing of the method is determined at run time.

这里就说的很清除了,变量是静态绑定的,方法是动态绑定的。

下面是相关的一个FAQ:

Q. If I remove the amethod() from the Base class defined in the above question, I got a compile error: ""method amethod() not found class Base". Why?
A: Incredible great question!!
    It will make you understand dynamic binding or polymorphism much much better.
    If you remove amethod() from Base class, you actually take amethod() out of the polymorphism between Base and SubBase class. Compiler only know b is refer to a Base class, which does not have the method amethod(), compile time error!!!
    Remember SubBase ISA Base. Compiler does not care which child/grandchild/grandgrandchild down the hierarchy b is actually referring to, and which amethod() it should call. However, they all have an amethod()
(polymorphism). It is a runtime decision. Dynamic Binding.
    Dynamic binding, or binding at runtime only for those methods defined in Base class , either inherited or overrided by the subclass. The override can be already happened now or will happen in the future, the compiler does not care.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息