Java中的继承

作者: Arvin Chen 分类: Java 来源: Break易站(www.breakyizhan.com)

继承的概念

继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。

继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

生活中的继承:

兔子和羊属于食草动物类,狮子和豹属于食肉动物类。

食草动物和食肉动物又是属于动物类。

所以继承需要符合的关系是:is-a,父类更通用,子类更具体。

虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。

Java中的继承

继承是OOP(面向对象编程)的重要支柱。它是一种允许一个类继承另一个类的特征(字段和方法)的java机制。
重要术语:

  • 超级类:其功能被继承的类被称为超级类(或基类或父类)。
  • 子类:继承其他类的类称为子类(或派生类,扩展类或子类)。除了超类字段和方法外,子类还可以添加自己的字段和方法。
  • 可重用性:继承支持“可重用性”的概念,即当我们想创建一个新类并且已经有一个包含我们想要的一些代码的类时,我们可以从现有类中派生出我们的新类。通过这样做,我们正在重用现有类的字段和方法。

如何在Java中使用继承

用于继承的关键字是扩展的。
句法 :

class 父类 {

}

class 子类 extends 父类 {

}

例子:在继承的例子中,类Bicycle自行车是一个基类,类MountainBike山地自行车是一个派生类,它扩展了Bicycle类,它是一个运行程序的驱动类。

//Java program to illustrate the
// concept of inheritance

// base class
class Bicycle
{
    // the Bicycle class has two fields
    public int gear;
    public int speed;

    // the Bicycle class has one constructor
    public Bicycle(int gear, int speed)
    {
        this.gear = gear;
        this.speed = speed;
    }

    // the Bicycle class has three methods
    public void applyBrake(int decrement)
    {
        speed -= decrement;
    }

    public void speedUp(int increment)
    {
        speed += increment;
    }

    // toString() method to print info of Bicycle
    public String toString()
    {
        return("No of gears are "+gear
                +"\n"
                + "speed of bicycle is "+speed);
    }
}

// derived class
class MountainBike extends Bicycle
{

    // the MountainBike subclass adds one more field
    public int seatHeight;

    // the MountainBike subclass has one constructor
    public MountainBike(int gear,int speed,
                        int startHeight)
    {
        // invoking base-class(Bicycle) constructor
        super(gear, speed);
        seatHeight = startHeight;
    }

    // the MountainBike subclass adds one more method
    public void setHeight(int newValue)
    {
        seatHeight = newValue;
    }

    // overriding toString() method
    // of Bicycle to print more info
    @Override
    public String toString()
    {
        return (super.toString()+
                "\nseat height is "+seatHeight);
    }

}

// driver class
public class Test
{
    public static void main(String args[])
    {

        MountainBike mb = new MountainBike(3, 100, 25);
        System.out.println(mb.toString());

    }
}

输出:

No of gears are 3
speed of bicycle is 100
seat height is 25

在上面的程序中,当创建一个MountainBike类的对象时,超类的所有方法和字段的副本将获取此对象中的内存。这就是为什么,通过使用子类的对象,我们也可以访问超类的成员。
请注意,在继承过程中,只创建子类的对象,而不是超类。

在实践中,java中一起使用继承和多态,以实现代码的快速性能和可读性。

Java中的继承类型

下面是Java支持的不同类型的继承。

需要注意的是 Java 不支持多继承,但支持多重继承。

单继承:在单继承中,子类继承一个超类的特性。在下图中,类A充当派生类B的基类。

Java中的继承

多级继承: 在多级继承中,派生类将继承基类,并且派生类也充当其他类的基类。在下面的图像中,类A充当派生类B的基类,而类B又是派生类C的基类。在Java中,类不能直接访问祖父类的成员。

Java中的继承

分层继承:在分层继承中,一个类作为多于一个子类的超类(基类)。在下图中,类A作为派生类B,C和D的基类。

Java中的继承

多继承(通过接口):在多继承中,一个类可以有多个超类,并从所有父类继承特征。请注意,Java并没有支持多重继承与类。在java中,我们只能通过接口实现多重继承。在下图中,C类来自界面A和B.

Java中的继承

混合继承(通过接口):它是两种或多种上述类型继承的混合。由于java不支持类的多重继承,所以混合继承对类也是不可能的。在java中,我们只能通过Interfaces来实现混合继承。

Java中的继承

Java中有关继承的重要事实

  • 默认超类:除了没有超类的Object类外,每个类都有且仅有一个直接超类(单继承)。在没有任何其他显式超类的情况下,每个类都隐式地是Object类的一个子类。
  • 超类只能是一个:超类可以有任意数量的子类。但是一个子类只能有一个超类。这是因为Java不支持多类继承。尽管使用接口,Java仍支持多继承。
  • 继承构造函数:一个子类继承其超类的所有成员(字段,方法和嵌套类)。构造函数不是成员,因此它们不会被子类继承,但可以从子类调用超类的构造函数。
  • 私有成员继承:子类不继承其父类的私有成员。但是,如果超类具有访问其专用字段的公共或受保护方法(如getter和setter),则这些方法也可以由子类使用。
  • 子类拥有父类非 private 的属性、方法。
  • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
  • 子类可以用自己的方式实现父类的方法。
  • Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 A 类继承 B 类,B 类继承 C 类,所以按照关系就是 C 类是 B 类的父类,B 类是 A 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
  • 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。

Java继承的关键字

继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类。

extends关键字

在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。

public class Animal { 
    private String name;   
    private int id; 
    public Animal(String myName, String myid) { 
        //初始化属性值
    } 
    public void eat() {  //吃东西方法的具体实现  } 
    public void sleep() { //睡觉方法的具体实现  } 
} 
 
public class Penguin  extends  Animal{ 
}

implements关键字

使用 implements 关键字可以变相的使java具有“多继承”的特性,使用范围为类继承接口的情况,可以同时实现(“继承”)多个接口(接口跟接口之间采用逗号分隔)。其实多继承的说法是错误的,应该叫做多实现,但是这里说的是打比方“多实现”。

public interface A {
    public void eat();
    public void sleep();
}
 
public interface B {
    public void show();
}
 
public class C implements A,B {
}

super 与 this 关键字

super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。

this关键字:指向自己的引用。

class Animal {
  void eat() {
    System.out.println("animal : eat");
  }
}
 
class Dog extends Animal {
  void eat() {
    System.out.println("dog : eat");
  }
  void eatTest() {
    this.eat();   // this 调用自己的方法
    super.eat();  // super 调用父类方法
  }
}
 
public class Test {
  public static void main(String[] args) {
    Animal a = new Animal();
    a.eat();
    Dog d = new Dog();
    d.eatTest();
  }
}

输出结果为:

animal : eat
dog : eat
animal : eat

final关键字

final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写:

  • 声明类:
    final class 类名 {//类体}
  • 声明方法:
    修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}

:实例变量也可以被定义为 final,被定义为 final 的变量不能被修改。被声明为 final 类的方法自动地声明为 final,但是实例变量并不是 final

Java继承的构造器

子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。

如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。

实例

class SuperClass {
  private int n;
  SuperClass(){
    System.out.println("SuperClass()");
  }
  SuperClass(int n) {
    System.out.println("SuperClass(int n)");
    this.n = n;
  }
}
// SubClass 类继承
class SubClass extends SuperClass{
  private int n;
  
  SubClass(){ // 自动调用父类的无参数构造器
    System.out.println("SubClass");
  }  
  
  public SubClass(int n){ 
    super(300);  // 调用父类中带有参数的构造器
    System.out.println("SubClass(int n):"+n);
    this.n = n;
  }
}
// SubClas2 类继承
class SubClass2 extends SuperClass{
  private int n;
  
  SubClass2(){
    super(300);  // 调用父类中带有参数的构造器
    System.out.println("SubClass2");
  }  
  
  public SubClass2(int n){ // 自动调用父类的无参数构造器
    System.out.println("SubClass2(int n):"+n);
    this.n = n;
  }
}
public class TestSuperSub{
  public static void main (String args[]){
    System.out.println("------SubClass 类继承------");
    SubClass sc1 = new SubClass();
    SubClass sc2 = new SubClass(100); 
    System.out.println("------SubClass2 类继承------");
    SubClass2 sc3 = new SubClass2();
    SubClass2 sc4 = new SubClass2(200); 
  }
}

输出结果为:

------SubClass 类继承------
SuperClass()
SubClass
SuperClass(int n)
SubClass(int n):100
------SubClass2 类继承------
SuperClass(int n)
SubClass2
SuperClass()
SubClass2(int n):200

什么都可以在一个子类中完成?

在子类中,我们可以按原样继承成员,替换它们,隐藏它们,或者用新成员补充它们:

  • 继承的字段可以直接使用,就像任何其他字段一样。
  • 我们可以在子类中声明不在超类中的新字段。
  • 继承的方法可以直接使用。
  • 我们可以在子类中编写一个与超类中签名相同的新实例方法,从而覆盖它(如上面的例子中,toString()方法被覆盖)。
  • 我们可以在子类中编写一个新的静态方法,该方法与超类中的签名具有相同的签名,从而隐藏它。
  • 我们可以在子类中声明不在超类中的新方法。
  • 我们可以编写一个子类构造函数,它可以隐式地或通过使用关键字super来调用超类的构造函数。
  •   本文标题:Java中的继承 - Break易站
    转载请保留页面地址:https://www.breakyizhan.com/java/4215.html

    发表笔记

    电子邮件地址不会被公开。 必填项已用*标注

    更多阅读