知识回顾8、继承和多态的问题2

二、访问成员变量和成员方法的问题

1、第一个例子

class Base
{
    private int i=2;
    public Base()
    {
        System.out.println(this.getClass());
        System.out.println(this.i);
        this.display();
        //this.sub();
    }
    public void display()
    {
        System.out.println("父类的方法");
        System.out.println(i);
    }
    
}
class Drib extends Base
{
    private int i=22;
    public Drib()
    {
        i=222;
    }
    public void display()
    {
        System.out.println("子类的方法");
        System.out.println(i);
    }
    public void sub()
    {
        
    }
}
public  class Test6
{
    public static void main(String[] args)
    {
        new Drib();
    }
}

输出结果是

class test.Drib
2
子类的方法
0

结果为什么是这样的奇怪。

this.getClass()返回Drib类,可是为什么调用的this.i是

分析一下程序的执行过程:

首先是new Drib();,初始化它之前,先要初始化父类。

那么,父类的int i=2;先初始化了,在执行父类的构造器,因为父类的构造器中有
        System.out.println(this.getClass());
        System.out.println(this.i);
        this.display();
        //this.sub();

这几句代码,那么就依次执行,可是从输出结果看来却很奇怪:

this.getClass()返回Drib类,说明this代表的是Drib类的this,

那么,为什么this.i调用的是父类的i,输出为2

为什么this.display()调用子类的display()

为什么this.sub()不能通过编译。

这个this,到底代表的是谁?

答案是,这个this是代表子类的对象没错,但是它却是一个父类的引用。


如果上面的答案你看的很糊涂,那么看下面的这个简单的例子,,从这个直接点的例子中就可以找到上面的答案

2、第2个例子
public class Test7
{
    public static void main(String[] args)
    {
        Demo1 d1=new Demo2();
        System.out.println(d1.getClass());
        d1.show1();
        d1.display();
        //d1.show2();
        ((Demo2)d1).show2();
        System.out.println(d1.a);
        System.out.println(((Demo2)d1).a);
    }
}
class Demo1
{
    int a=2;
    public void show1()
    {
        System.out.println("父类的show1");
    }
    public void display()
    {
        System.out.println("父类的display");
    }
}
class Demo2 extends Demo1
{
    int a=3;
    public void show1()
    {
        System.out.println("子类的show1");
    }
    public void show2()
    {
        System.out.println("子类的show2");
    }
}
在这里,我们new了一个子类Demo2的对象,确实用的父类的引用。

然后执行

 System.out.println(d1.getClass());结果表明这是个Demo2的对象,这说明,虽然我们用的是父类的引用,可是这实际上是一个子类的对象。你是否想到了什么,

没错就如同第一例子的this一样,虽然他是子类的this,但是引用确实父类的。     


在看d1.show1();这里执行的是谁的show1();答案是子类的,为什么是父类的引用,执行的是子类的show1(),这是因为父类的show1()被子类所覆盖了。这就是为什么上个例子中为什么执行的是子类的display() 一样。


在看 d1.display();因为子类中没有重写display,所以调用父类的display().


再看 //d1.show2();这句话不能通过编译,因为这是一个父类的引用,而父类根本没有show2()的方法,所以不能引用,这就是上个例子中this.sub()不能通过的一样的原因。

要想调用子类的show2(),就只能先强转一下,((Demo2)d1).show2();


再看System.out.println(d1.a);,输出的结果是2,是父类的a=2;

他娘的,方法被覆盖了,调用方法的时候,是调用子类的方法;变量也覆盖了,为什么调用的又是父类的变量?

是不是很纠结,其实,继承关系中,方法是可以被完全覆盖,但是变量不会被覆盖,只是你找不到这个变量的引用而已。

在看下面一段很简单的代码

        Demo2 d2=new Demo2();
        ((Demo1)d2).show1();
        System.out.println(((Demo1)d2).a);

你会发现,就算你强转一下d2,调用的依然是子类的show1,但是调用的变量确实父类的了。

这就说明,父类方法确实在继承的过程完全覆盖了,但父类变量却只是失去了引用,当你给他这个引用的时候,就可以调用父类的变量了。(个人理解)

System.out.println(d1.a);输出的是父类的2;


  在看
        System.out.println(((Demo2)d1).a);

将d1强转一下,那么引用又变成子类的了,这样结果又变成了3。






所以,在调用的问题中记住几点:

(1)、自己的引用可以调用自己的成员变量和成员方法

(2)、子类的引用不能引用父类的对象

(3)、父类的引用可以引用子类的对象,但是该引用调用的所有变量都是自身的变量

调用的方法:

如果是父类的方法并且没有被ilei重写,那么调用自己的

如果是父类的方法被子类重写了,调用子类的

如是是子类独有的方法和变量,父类不能调用




      


你可能感兴趣的:(String,Class)