08.第十一章:继承和多态(1)

1. 面向对象的编程允许你从已经存在的类中定义新的类 , 这称为继承。
2. 继承使得你可以定义一个通用的类 ( 即父类 ) , 之后扩充该类为一个更加特定的类 ( 即子类 ) 。
3. super关键字
  • 调用父类的构造方法
    构造方法用于构建一个类的实例 。 不同于属性和普通方法 , 父类的构造方法不会被子类继承 。 它们只能使用关键字 super 从子类的构造方法中调用 。
    super () 或者 super ( parameters )
    • 构造方法链
      • 构造方法可以调用重载的构造方法或父类的构造方法 。 如果它们都没有被显式地调用 ,编译器就会自动地将 superO 作为构造方法的第一条语句 。
      • 在任何情况下 , 构造一个类的实例时 , 将会调用沿着继承链的所有父类的构造方法 。 当构造一个子类的对象时 , 子类构造方法会在完成自己的任务之前 , 首先调用它的父类的构造方法 。 如果父类继承自其他类 , 那么父类构造方法又会在完成自己的任务之前 , 调用它自己的父类的构造方法 。 这个过程持续到沿着这个继承体系结构的最后一个构造方法被调用为止。这就是构造方法链 ( constructor chaining ) 。
08.第十一章:继承和多态(1)_第1张图片
  • 调用父类的方法 super . 方法名 ( 参数 )
4.方法的重写

子类从父类中继承方法 。 有时 , 子类需要修改父类中定义的方法的实现 , 这称作方法重写 ( method overriding ) 。
注意:

  • 仅当实例方法是可访问时 , 它才能被覆盖 。 因为私有方法在它的类本身以外是不能访问的 , 所以它不能被覆盖 。 如果子类中定义的方法在父类中是私有的 , 那么这两个方法完全没有关系。
  • 与实例方法一样 , 静态方法也能被继承 。 但是 , 静态方法不能被重写。
  • 方法重写具有同样的签名和返回值类型 ; 方法重载具有同样的名字 , 但是不同的参数列表 。
5.多态
  • 使用父类对象的地方都可以使用子类的对象 ,这就是通常所说的多态。简单来说 , 多态意味着父类型的
    变量可以引用子类型的对象 。
  • 动态绑定
Object o = new CeometricObject () ;
System . out . println ( o . toString ( ) );

声明类型:一个变量必须被声明为某种类型 。 变量的这个类型称为它的声明类型 。 这里 , o 的声明类型是 Object 。
实际类型:被变量引用的对象的实际类。 这里 , o 的实际类型是 GeometricObject , 因为 o 指向使用 new GeometricObject()创建的对象。
o 调用哪个toString()方法由 o 的实际类型决定,这称为动态绑定。

6.示例:
  • 方法的重写(仅当实例方法是可访问时 , 它才能被覆盖 ,否则是完全不同的两个方法)
public class Test1 {
    public static void main(String[] args) {
        new Personl().printPerson();
        new Student().printPerson();
    }
}
    class Student extends Personl {
    //因为声明的是private,所以子类的方法与父类的同名方法毫无关系
    //没有重写父类的方法
        private String getlnfo(){
            return "Student";
        }
    }

     class Personl {
         private String getlnfo() {
             return "Person";
         }
         //父类调用父类的getInfo()方法
         public void printPerson() {
             System . out . println (getlnfo()) ;
         }
     }

结果为Person Person

public class Test1 {
    public static void main(String[] args) {
        new Personl().printPerson();
        new Student().printPerson();
    }
}
    class Student extends Personl {
     //声明为public,子类重写了父类的方法,在子类对象调用时,会使用重写的方法
        public String getlnfo(){
            return "Student";
        }
    }

     class Personl {
         public String getlnfo() {
             return "Person";
         }
         //父类调用父类的getInfo()方法,但如果是子类对象调用,父类的getInfo方法已经被重写
         public void printPerson() {
             System . out . println (getlnfo()) ;
         }
     }

结果 Person Student

  • 创建一个对象时 构造函数的运行过程:先调用父类的构造函数,再调用子类的构造函数
ackage java_04_基础习题练习.第11章_继承和多态;

/**
 *
 */
public class Test2_构造函数执行顺序 {
    public static void main(String[] args){
        A a=new A(3);
    }
}
class A extends B{
    public A(int t){
        System.out.println("A's constructor is invoked");
    }

}
class B{
    public B(){
        System.out.println("B's constructor is invoked");
    }
}
public class Test3 {
    public static void main(String[] args){
        //直接调用A1的构造函数,i=40
        new A1();
        //1.B1继承自A1,先去执行A1,给i赋值i=7;
        //2.调用A1的构造函数,由于setI()方法被子类重写,所以此时调用的是子类的setI()方法,i=60
        //3.i from A is 60
        //4.调用B1的构造函数,i在A1中已经被赋值60,所以i from B is 60
        new B1();
    }
}

class A1{
    int i=7;
    public A1(){
        setI(20);
        System.out.println("i from A is "+i);
    }

    public void setI(int i){
        this.i=2*i;
    }
}

class B1 extends A1{
    public B1(){
        System.out.println("i from B is "+i);
    }
    public void setI(int i){
        this.i=3*i;
    }
}
  • instanceof:
    在尝试转换之前确保该对象是另一个对象的实例,可以利用运算符 instanceof来实现。
    警告 : 对象成员访问运算符 ( . ) 优先于类型转换运算符 。 使用圆括号保证在点运算符 ( • )
    之前进行转换 , 例如 :( ( Circle) object ) . getArea();
7.Object 类的 equals 方法

Object类中方法的默认实现:

//这个实现使用 == 运算符检测两个引用变量是否指向同一个对象。
//因此 , 应该在自己的客户类中重写这个方法 , 以测试两个不同的对象是否具有相同的内容 。
public boolean equals ( Object o ){
   return(this==obj);
}

调用语法:object1. equals ( object2 ) ;

你可能感兴趣的:(08.第十一章:继承和多态(1))