Java——类的继承与多态

1. 在子类中,若要调用父类中被覆盖的方法,可以使用super关键字。

以以下代码为例解释:

package homework;

 

class Grandfather{

       public Grandfather(){

              System.out.println("Grandfather created. ");

       }

}

class TestParent extends Grandfather{

       public TestParent(){

              System.out.println("Father  created. ");

       }

      

       public void show() {

              System.out.println("This is father's words ");

       }

      

}

 

class TestChild extends TestParent{

 

       public TestChild(){

              System.out.println("Child created. ");

       }

        

       public void show() {

              super.show();

              System.out.println("This is my words ");

       }

      

}

public class TestClassP_C {

 

       public static void main(String[] args) {

              // TODO Auto-generated method stub

             

              TestChild c=new TestChild();

              //依次继承

              c.show();

              //调用TestChild中show()函数,由于函数中有super,因此调用父类中被覆盖的show()方法

       }

 

}

(1)关于子类的创建:

若父类及父类的父类有默认构造函数,则从最底层(最开始的父类)开始继承,直到传递到子类。

(2)关于super的使用:

首先super主要用来调用父类的方法,必须放在每一个子类构造函数的第一句,并不是指类中的第一句。

其次,若是子类函数想调用父类中被覆盖的函数方法,可通过“super.方法名()”调用到父类中的函数;若是子类构造函数,则直接使用“super()”(无参时)或者“super(参数值)”(有参时)调用父类的构造函数。

(3)编译错误分析:

在编译时,不断尝试不同的构造方法和调用方法,发现以下错误:

若父类多了一个有参的构造函数,要么子类构造函数保持一致,super(参数值)调用,要么不写子类构造函数。否则会显示错误。具体如下:

父类构造函数有参

使用无参super会错误,即使没有使用super也错误。

 

 

Super和子类构造函数均加参数才正确

2.子类与父类的类型转换与使用总结:

观察以下代码:

class Mammal{}

class Dog extends Mammal {}

class Cat extends Mammal{}

 

public class TestCast

{

       public static void main(String args[])

       {

              Mammal m;

              Dog d=new Dog();

              Cat c=new Cat();

              m=d;

              //d=m;//错误!父类m赋值给子类d,需要进行(Dog)m强制类型转换。

              d=(Dog)m;

              //d=c;//错误!两个子类不能能相互赋值。

//            c=(Cat)m;//编译正确,通过强制类型转换,可以将父类变量赋给子类。

 

       }

}

 总结:

子类可以给父类直接赋值,比如“m=d;”;但是若父类需要给子类赋值,需要进行类的强制类型转换。可以想象成现实中的亲子关系,父母给孩子是爱的表达,这里面表达了很多;而孩子给父母是天经地义,可以直接给,加强记忆。

另外两个派生类之间没有关联,不予赋值,就像亲兄妹,没有义务给予经济支持。

3. 接口多态:使用接口代替抽象基类

首先区分接口与抽象基类的定义。

接口:在表面上由几个没有主体代码的方法定义成的集合体,有唯一的名称,可以被继承或其他接口所实现。使用接口主要实现多态性。一个类一次可以实现若干个接口,但一个类只能继承一个父类。需要注意的是,定义在接口中的常量必须被初始化。

抽象类则是为了使代码复用,可根据实际的编程环境,选择方法。

4. .分析下方的程序运行结果是什么,并解释会得到这样的输出

 

假设parent.myvalue=100,child.myvalue=200。

第一次新建Parent和Child类时,会调用各自的printvalue()函数;分别输出100,200.

当“Parent=child”时,将child的对象赋给parent,于是再调用“parent.printvalue()”,输出child.myvalue=200;执行“parent.myValue++”,则为parent的myvalue=101。由于子类中重新定义了printValue()方法,覆盖掉了父类中的方法,故即使再调用“Parent.printValue()”依旧输出child.myValue=200。当执行“((child)parent).myValue++”,意思为将parent转化为child,实际调用child.myValue++即201,再次由于父类方法被覆盖,“parent.printValu()”依旧输出child.myValue=201。

总结:

当子类与父类拥有一样的方法,并且让一个父类变量引用一个子类对象时,到底调用哪个方法,由对象自己的“真实”类型所决定。这就是说:对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。

如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。如果子类被当作父类使用,则通过子类访问的字段是父类的!

实际运用中,尽量避免命名与父类相同的方法。

原文地址:https://www.cnblogs.com/somedayLi/p/7805708.html