• 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;
            
        }
        }

  • 相关阅读:
    闭包装饰器与递归
    内置函数学习
    可迭代对象 迭代器 生成器 推导式 匿名函数
    函数基础
    python文件操作
    深浅copy与小数据池
    python数据类型
    python基础语法
    view视图函数的书写 请求与响应相关
    LeetCode OJ:Rotate Image(旋转图片)
  • 原文地址:https://www.cnblogs.com/watm/p/7808958.html
Copyright © 2020-2023  润新知