6继承与多态

一、动手实验:继承条件下的构造方法调用

观察输出,注意总结父类与子类之间构造方法的调用关系修改Parent构造方法的代码,显式调用GrandParent的另一个构造函数,注意这句调用代码是否是第一句,影响重大!
结论:通过 super 调用基类构造方法,必须是子类构造方法中的第一个语句。
 1 class Grandparent
 2 {
 3     public Grandparent()
 4         {
 5                 System.out.println("GrandParent Created.");
 6         
 7 }
 8     public Grandparent(String string)
 9         {
10                 System.out.println("GrandParent Created.String:" + string);
11         
12  }
13 }
14 class Parent extends Grandparent
15 {
16     public Parent()
17          {
18                 //super("Hello.Grandparent.");
19                 System.out.println("Parent Created");
20         
21        // super("Hello.Grandparent.");
22           }
23 }
24 class Child extends Parent
25 {
26     public Child()
27          {
28         
29         System.out.println("Child Created");
30           }
31 }
32 public class TestInherits
33 {
34     public static void main(String args[])
35          {
36                 Child c = new Child();
37         
38   }
39 }
View Code

结果截图:

当super("Hello.Grandparent")出现在子类构造方法非注释语句的第一行语句,否则报错。

思索:为什么子类的构造方法在运行之前,必须调用父类的构造方法?能不能反过来?为什么不能反过来?

因为在调用子类前会首先调用父类,即父类的构造函数会首先运行。

二、在子类中,若要调用父类中被覆盖的方法,可以使用super关键字。方法覆盖要求子类与父类的方法一模一样,否则就是方法重载(overload)。

class Monther
{
        public Monther()
        {
                System.out.println("Monther created.");
        }
        public void display()
        {
                System.out.println("Monther is displayed");
        }
        }
class Child extends Monther
{
        public Child()
        {
                System.out.println("Child created");
        }
        public void display()
        {
                super.display();
                System.out.println("Child displayed");
        }
        }
public class Same {
public static void main(String []args)
{
        Child c=new Child();
        c.display();
        }
        
}

结果截图:

java覆盖的语法规则:

(1)覆盖方法的允许访问范围不能小于原方法。

(2)覆盖方法所抛出的异常不能比原方法更多。

(3)声明为final方法不允许覆盖。    例如,Object的getClass()方法不能覆盖。

(4)不能覆盖静态方法。

三、“类型转换”知识点考核

现在有三个类:
class Mammal{}
class Dog extends Mammal {}
class Cat extends Mammal{}
针对每个类定义三个变量并进行初始化   
 Mammal m=null ;    
Dog d=new Dog();    
Cat c=new Cat();
下列语句哪一个将引起编译错误?为什么?哪一个会引起运行时错误?为什么?        
m=d;   //true  子类赋值给父类
d=m;    //false 
d=(Dog)m;   //true   已知m=d,故m为Dog型可以赋值给d而不能给c。
d=c;        //false
c=(Cat)m;//false
四、在实践中理解把握复杂的知识
public class ParentChildTest {
        public static void main(String[] args) {
                Parent parent=new Parent();
                parent.printValue();
                Child child=new Child();
                child.printValue();
                
                parent=child;
                parent.printValue();
                
                parent.myValue++;//调用的parent.myValue
                parent.printValue();
                
                ((Child)parent).myValue++;//调用child.myValue
                parent.printValue();
                
        }
}
class Parent{
        public int myValue=100;
        public void printValue() {
                System.out.println("Parent.printValue(),myValue="+myValue);
        }
}
class Child extends Parent{
        public int myValue=200;
        public void printValue() {
                System.out.println("Child.printValue(),myValue="+myValue);
        }
}
1.   左边的程序运行结果是什么?你如何解释会得到这样的输出?
Parent.printValue(),myValue=100 //调用Parent
Child.printValue(),myValue=200  //调用Child
Child.printValue(),myValue=200  //调用child
Child.printValue(),myValue=200 //调用child
Child.printValue(),myValue=201  //调用child
2.   计算机是不会出错的,之所以得到这样的运行结果也是有原因的,那么从这些运行结果中,你能总结出Java的哪些语法特性?
1)当子类与父类拥有一样的方法,对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。
2)如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。如果子类被当作父类使用,则通过子类访问的字段是父类的!若将子类赋值给父类,则通过父类引用的方法是子类的,而调用的变量是父类的。(子类对象赋值给父类对象时,重写了父类方法,则属性是父类的,方法是子类的)
五、.多态编程有两种主要形式:(1)继承多态(2)接口多态:使用接口代替抽象基类。
Java中“接口”的语法特性:
定义一个接口,采用关键字interface,实现一个接口,采用关键字implements
接口的成员函数自动成为public的,数据成员自动成为 static和final的。
如果接口不声明为public的,则自动变为package。
一个类可以同时实现多个接口。
接口类型  接口类型的变量=new 实现了接口的具体类型()
可以通过继承接口来扩充已有接口,并形成一个新的接口。      
interface OneInterface {
void f1();}
interface TwoInterface extends OneInterface 
{void f2();}
实现子接口的类,必须实现“父”“子”接口所定义的所有方法,才能被实例化(即new出一个对象)。
public interface ArrayBound
 {    public static final int LOWBOUND=1;    
public static final int UPBOUND=100;
}只要一个类声明实现了这个接口,就可以直接使用这些常量名。
在实际开发中,这种编程方式非常常见。
注意:定义在接口中的常量必须被初始化。
抽象类是一个不完全的类,而接口只是表明类应该具有哪些“外部”特征,不涉及任何实现细节。
接口基本上不具备继承的任何具体特点,它仅仅承诺了外界能够调用的方法。
一个类一次可以实现若干个接口,但一个类只能继承一个父类。
import static java.lang.System.out;
public class Interface{
    public static void main(String []args)
    {
        Shape shape=new Circle(5);
        out.println(shape.area());
    }
}
interface Shape
{
    double area();
    }
class Circle implements Shape
{
    private double r;
    public Circle(double _r)
    {
        this.r=_r;
    }
    
    public double area()
    {
        return Math.PI*r*r;
        
    }
    }

原文地址:https://www.cnblogs.com/watm/p/7808958.html