美文网首页编程
Java继承和多态

Java继承和多态

作者: Golden30 | 来源:发表于2018-02-22 09:24 被阅读61次

    Java继承和多态

    继承

    定义

    继承就是利用现有类创建新类的过程,现有的类称为 父类(基类),新类称为 子类(派生类)。比如现实中:儿子继承了父亲遗产一样。面向对象程序设计中的继承,就是代码重用。
    Java中所有的类都继承自 Object 这个父类。

    实现

    在Java中实现继承需要使用到extends关键字;

    [访问修饰符] class 派生类名 extends 基类名 {
            成员列表
        }
    

    如:

    class Student extends Person
    {
        ……
    }
    

    访问修饰符 请参看之前章节的内容。

    例子

    例:

    定义抽象类:Person。

    public abstract class Person {  // 抽象类
        private String name;  // 私有变量
        
        public String getName() {  // Getter方法
            return name;
        }
        public void setName(String name) {  //Setter方法
            this.name = name;
        }
            
        public Person(String name) {  // 构造函数,用于初始化name
            super();
            this.name = name;
        }
        public abstract String getDesc();  // 抽象类中的抽象方法。  只有声明,没有具体实现。
      
          public String toString(){      // toString方法覆盖了Object类的toString方法
             return name + getDesc();
          }
    }
    
    public class Student extends Person {  // 继承类
        private String major; // 新增加的数据    
        
        public String getMajor() {
            return major;
        }
        
        public void setMajor(String major) {
            this.major = major;
        }    
        
        public Student(String name,String major) { // 构造函数用于初始化
            super(name);   // 调用超类构造函数
            this.major = major;
        }
        
        @Override
        public String getDesc() {  // 必须实现超类中的抽象方法
            // TODO Auto-generated method stub
            return " : a student, major is " + major;
        }
    

    继承的作用

    • 当今软件设计的特征
      软件规模越来越大
      软件设计者越来越多
      软件设计分工越来越细
    • 引入继承,实现了代码重用;
    • 引入继承,实现了递增式的程序设计。
    • 继承是能自动传播代码和重用代码的有力工具;
    • 继承能够在某些比较一般的类的基础上建造、建立和扩充新类;
    • 能减少代码和数据的重复冗余度,并通过增强一致性来减少模块间的接口和界面,从而增强了程序的可维护性;
    • 能清晰地体现出类与类之间的层次结构关系。

    注意事项

    • 继承是单方向的,即派生类可以继承和访问基类中的成员,但基类则无法访问派生类中的成员; 父类不能访问子类方法
    • 在Java中只允许 单一继承 方式,即一个派生类只能继承于一个基类,而不能象C++中派生类继承于多个基类的多重继承方式。

    继承中的构造方法

    • 父类中的构造方法可以被重载,但不能被子类继承,即便它是public的;
    • 父类的构造方法负责初始化属于它的成员变量,而子类的构造方法则只需考虑属于自己的成员变量,不必去关注父类的情况。
    • 当实例化子类的对象时,必须先执行父类的构造方法,然后再执行子类的构造方法;
    • 如果父类还有更上级的父类,就会先调用最高父类的构造方法,再逐个依次地将所有继承关系的父类构造方法全部执行;
    • 如果父类的构造方法执行失败,那么子类的对象也将无法实例化。

    class ParentClass {  //定义父类
      public ParentClass() {  //构造方法
        System.out.println("这是父类的构造方法。");
      }
    }
    
    class ChildClass extends ParentClass {  //子类继承于父类
      public ChildClass() {  //构造方法
        System.out.println("这是子类的构造方法。");
      }
    }
    
    public class ConstructorTest {  //该类用于容纳main方法
      public static void main(String[] args) {
        ChildClass cc = new ChildClass();  //实例化子类对象
      }
    }
    

    super

    如果子类需要调用父类的方法或者属性怎么办?

    • 在子类的构造方法中,super关键字可以显式地调用父类的构造方法,用于将参数传递给它;需要注意的是: 该语句必须是子类构造方法的第一条语句

    如:

    class Point  //定义"点"类
    {
      protected float mX, mY;  //x轴坐标和y轴坐标
    
      public Point(float x, float y)  //构造方法
      {
        mX = x;
        mY = y;
      }
      ……
    }
    
    class Circle extends Point  //定义"圆"类继承于"点"类
    {
      protected float mRadius;    //半径
    
      public Circle(float x, float y, float r)  //构造方法
      {
        super(x, y);  //显式调用父类构造方法,必须是第一条语句
        mRadius = r;
      }
      ……
    }
    
    • 如果父类和子类中有同名成员,在子类中默认访问是属于自己的那一个成员;super关键字可以明确地指定要访问父类中的成员;但前提条件是:父类中的该成员不是private的

    多态

    方法覆盖

    定义
    • 在类的继承体系结构中,如果子类中出现了与父类中有同原型的方法,那么认为子类中的方法覆盖了父类中的方法(也称为方法重写);
    • 通过子类的实例调用被覆盖的方法时,将总是调用子类中的方法,而父类中的方法将被隐藏。

    如:

    /*如果不但名称相同,而且连方法原型也完全相同的话,则构成方法覆盖*/
    class ParentClass {  //定义父类
      public void fun() {
        System.out.println("这是父类中的方法。");
      }
    }
    
    class ChildClass extends ParentClass {//子类继承于父类
      public void fun() {  //子类覆盖父类中的方法
        System.out.println("这是子类中的方法。");
      }
    }
    
    class OverriddenTest {  //用于容纳main方法
      public static void main(String[] args) {
        ParentClass parObj = new ParentClass();
        parObj.fun();  //父类的实例调用此方法
    
        ChildClass chiObj = new ChildClass();
        chiObj.fun();  //子类的实例调用此方法
      }
    }
    
    方法覆盖的注意事项
    • 子类中重写的方法,其访问权限不能比父类中被重写方法的访问权限更低
    • 在子类中重写方法时要保持方法的签名与父类中方法的签名一致

    引用转型

    • 基类(父类)的引用可以指向派生类(子类)的对象。

    如:

    BaseClass obj = new DerivedClass();
    
    • 如果存在方法覆盖,那么将会调用其派生类中的方法

    如:

    class Shapes {  //基本形状类
      public void draw() {  //绘图的方法
        System.out.println("绘制了一个基本形状。");
      }
    }
    class Circle extends Shapes {  //圆形类继承于基本形状类
      public void draw() {  //覆盖父类的绘图方法
        System.out.println("绘制了一个圆形。");
      }
    } 
    class Square extends Shapes {  //正方形类继承与基本形状类
      public void draw() {  //覆盖父类的绘图方法
        System.out.println("绘制了一个正方形。");
      }
    }
    public class polymorphismDemo {
      public static void main(String[] args) {
        Shapes obj = new Shapes();  //父类的引用指向父类的实例
        obj.draw();                 //调用绘图方法
        obj = new Circle();         //父类的引用指向子类的实例
        obj.draw();                 //调用绘图方法
        obj = new Square();         //父类的引用指向子类的实例
        obj.draw();                 //调用绘图方法
      }
    }
    

    多态

    在Java中,使用父类的引用,调用同一个方法,却可以得到不同的调用结果,这就是多态。即: 同一函数,多种形态。
    实际上多态包括 动态多态静态多态

    静态多态
    • 静态多态也称为编译时多态,即在编译时决定调用哪个方法;
    • 静态多态一般是指方法重载;
    • 只要构成了方法重载,就可以认为形成了静态多态的条件;
    • 静态多态与是否发生继承没有必然联系。
    动态多态

    动态多态也称为运行时多态,即在运行时才能确定调用哪个方法。
    形成动态多态必须具体以下条件:

    • 必须要有继承的情况存在;
    • 在继承中必须要有方法覆盖;
    • 必须由基类的引用指向派生类的实例,并且通过基类的引用调用被覆盖的方法;

    由上述条件可以看出,继承是实现动态多态的首要前提。

    抽象

    抽象方法

    基类无法(或者没有必要)提供被覆盖方法的具体实现,那么就可以将这个方法定义为 抽象方法

    [访问权限] abstract 返回值类型 方法名(参数列表){
    }
    

    如:

    public abstract void draw(){
    }
    
    抽象类

    如果某个类包含抽象方法,那么这个类就必须定义成 抽象类

    [访问权限] abstract class 类名{
        成员列表
    }
    

    如:

    public abstract class Shapes{
        public abstract void draw();
    }
    
    抽象类的注意事项
    • 抽象类不可以直接实例化,只可以用来继承;
    • 抽象类的派生子类应该提供对其所有抽象方法的具体实现;
    • 如果抽象类的派生子类没有实现其中的所有抽象方法,那么该派生子类仍然是抽象类,只能用于继承,而不能实例化;
    • 抽象类中也可以包含有非抽象的方法;
    • 构造方法和静态方法不可以修饰为abstract。

    如:

    abstract class Shapes {  //基本形状类,抽象类
        public abstract void draw();  //绘图方法,抽象方法
    }
    class Circle extends Shapes {  //圆形类继承于基本形状类
        public void draw() {  //实现抽象父类的抽象绘图方法
            System.out.println("绘制了一个圆形。");
        }
    }
    class Square extends Shapes {  //正方形类继承与基本形状类
        public void draw() {  //实现抽象父类的抽象绘图方法
            System.out.println("绘制了一个正方形。");
        }
    }
    public class abstractDemo {  //该类用于容纳main方法
        public static void main(String[] args) {
            Shapes obj;
            obj = new Circle();         //父类的引用指向子类的实例
            obj.draw();                 //调用绘图方法
            obj = new Square();         //父类的引用指向子类的实例
            obj.draw();                 //调用绘图方法
        }
    }
    

    接口

    接口定义

    如果某个类中所有的方法都是 抽象方法,那么可以考虑将该类定义为接口。

    [访问权限] interface 接口名{
        成员列表
    }
    

    如:

    public interface IMyInterface{
        public void doIt();
    }
    
    实现接口

    接口只能用于实现,不能实例化(new)

    [访问权限] class 类名 implements 接口名 {
        成员列表
    }
    

    如:

    public class MyClass implements IMyInterface {
        public void doIt(){
        }
    }
    
    接口的注意事项
    • 接口中不能定义非抽象方法,也就是说接口中不能包含有函数实体。
      接口中的所有方法都默认为抽象方法,无需在每个方法前加abstract关键字。
    • 接口的实现类应该提供对接口中所有抽象方法的具体实现,否则将成为抽象类。
      与抽象类和它的继承类相似,也可以使用接口的引用指向其实现类的对象,从而达到动态多态的效果。
    • Java只支持单继承,而不能象C++那样可以多重继承,接口正是为了弥补这一点。
    • Java中还允许一个接口继承于另一个接口,即由父接口派生出子接口。

    如:

    public interface 子接口名 extends 父接口名 {
        成员列表
    }
    

    final关键字

    final修饰变量

    如果将某个变量修饰为final,那么该变量就成为 常量
    如:

    final double PI = 3.14159;
    

    ☆ 常量在声明时必须初始化。

    final修饰方法

    如果将某个成员方法修饰为final,则意味着该方法 不能被子类覆盖
    如:

    public final void fun() {
        ……
    }
    //如果在派生类中出现同原型的方法,将会报错。
    
    final修饰类

    如果将某个类修饰为final,则说明该类 无法被继承
    如:

    public final class MyClass {
        ……
    }
    //任何类想继承于MyClass类都将报错。
    

    类和类之间的关系

    • 有——>has
      汽车有轮子。一般来说这种关系对应的是 属性

    • 是——>is
      圆形是个形状。一般来说这种关系对应的是 方法

    相关文章

      网友评论

        本文标题:Java继承和多态

        本文链接:https://www.haomeiwen.com/subject/ntpatftx.html