7

龙生九子-浅谈Java的继承

 4 years ago
source link: http://www.cnblogs.com/jiaweixie/p/12538901.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

龙生九子-浅谈Java的继承

NZjYzqn.jpg!web

书接上回,我们之前谈过了类和对象的概念,今天我来讲一讲 面向对象程序设计 的另外一个基本概念— 继承

目录

  • 为什么需要继承
  • 自动转型与强制转型
  • 继承能干啥
  • 复写和隐藏
  • super关键字
  • 多态的概念

为什么需要继承

我们先先念一遍定义:利用继承,人们可以基于已存在的类构造一个新类。继承已存在的类就是复用(继承)这些类的方法和属性。在此基础上,还可以添加一些新的方法和属性,以满足新的需求。这是Java程序设计中的一项核心技术。

举个简单例子。俗话说 龙生九子,各有所好 ,我们把 龙王 当成 父类 ,他有九个儿子,相当于九个 子类 。每个子类都 继承 了父辈的真龙血脉(欧拉!),但是他们各有不同,擅长做不同的事情,相当于子类实现了 新的方法和属性 ,以满足不同的需求。而且需要注意的是九子只有一个 爸爸 ,也就是一个子类只能继承 一个父类 ,不允许认多个爸爸(龙王:逆子!)。

举一个更贴近生活的例子。我们有一个Employee类来表示公司的员工,这个公司中经理的待遇与普通雇员的待遇存在这一些差异。不过,他们之间也存在这很多相同的地方例如,他们都领薪水。只是普通的员工在完成本质工作后仅领取薪水,而经理在完成了预期的业绩之后还能得到奖金。这种情况就需要使用继承。这是因为需要为经理定义一个新类Manager,以便增加一些新功能。但可以 重用 Employee类中已经编写的部分代码。

码来!

//创建一个Manager类继承employee类
//关键字:extends(继承)
public class Manager extends Employee
{
  private double bonus;
  ...//此处省略
  public void setBonus(double bonus)
 {
  this.bonus = bonus;
  }

}

关键字extends表明正在构造的新类派生于一个已存在的类。我们可以看到,我们新建了一个 Manager类,他继承了 Employee类。那么,我们称 Employee父类Manager子类

自动转型和强制转型

父慈子孝

public class Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Animal");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Animal");
    }
}

public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Cat");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Cat");
    }
    public void eatMouse(){
        System.out.println("I am a cat,so I can eat rats!");
    } 

    public static void main(String[] args) {
        Cat myCat = new Cat();
        Animal myAnimal = myCat; //这是自动转型
        
        Cat anotherCat = (Cat)myCat; //这是强制转型
        //myAnimal.testClassMethod();
        //myAnimal.testInstanceMethod();
    }
}

先看代码,我们新建了两个类: 父类 Animal 和子类 Cat 。我没看到在 public static void main(String[] args) 中,我们创建了一个Cat类的实例 myCat 。

接下来,我们把这个 myCat 赋值给了 Animal 类型的实例 myAnimal

这一步是什么意思呢? 我们可以这样想,一只猫一定是一只动物,所以把一个猫对象 赋给 一个动物对象是合情合理的。非常自然,我们称之为 自动转型

但是值得注意的是当我们把 Cat 转型为 Animal 后,他就不能再调用子类特有的方法了,比如吃老鼠方法 eatMouse() ,因为你不能说任何一只动物都可以吃老鼠吧。我们没有在父类中实现这个吃老鼠方法,所以就不能调用。

再往下看 Cat anotherCat = (Cat)myCat; ,我们又把myCat 转型为 Cat型实例。但是我们在 myCat之前要加一个 (Cat) 这就是 强制转型 。但是要 注意 ,在 强制转型 之前,一定要有 自动转型 。因为你不能随便把一只动物就变成一只猫吧。编译器会自动进行运行时检查这个对象是否真的是 Cat类型 对象。

继承能干啥

来来来,继承的好处都有啥,谁答对了就给他(笑)

我们先简单的预览一下:

  • 子类可以直接使用父类的属性和方法。
  • 你可以声明一个和父类同名的属性,因此父类被 隐藏 (不推荐这样做)。
  • 你可以新增父类没有的属性和方法。
  • 你可以写和父类具有相同 签名 的实例方法,这称为 复写
  • 你可以写和父类具有相同 签名 的静态方法,这称为 隐藏
  • 你可以创建子类独有的新方法。
  • 你可以使用 super 关键字,在子类的构造方法中调用父类的构造方法。

接下来的我们将重点介绍 隐藏,复写,super的概念。

Definition:Two of the components of a method declaration comprise the method signature —the method's name and the parameter types.

补充说明:方法的 签名 由,方法名和参数类型构成。

calculateAnswer(double, int, double, double)

复写和隐藏

接下来我们介绍一下,复写和隐藏的概念。

码来:

public class Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Animal");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Animal");
    }
}

public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Cat");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Cat");
    }

    public static void main(String[] args) {
        Cat myCat = new Cat();
        
        myCat.testClassMethod();
        Animal myAnimal = myCat;
        myAnimal.testClassMethod();
        myAnimal.testInstanceMethod();
    }
}

我们新建了两个类,其中 Animal 为父类, Cat 为子类。他们分别实现了,一个静态方法 testClassMethod() ,一个实例方法 testInstanceMethod()

public static void main(String[] args) 中我们先创建了一个 Cat 实例 myCat ,再调用了他的静态方法,再把 myCat 自动转型为 Animal 的实例 myAnimal 。再分别调用它的静态方法和实例方法。

结果如下:

ZjEr6rM.png!web

第一行,我们用 myCat调用了静态方法,所以打印出了 The static method in Cat

我们把 myCat 自动转型后再次调用静态方法,结果发现,他调用的是父类的静态方法。

我们称此为隐藏,调用的结果取决于他是 子类 还是 父类 ,当子类调用静态方法时,父类的静态方法 被隐藏

我们看到最后一行,明明我们是用父类的实例调用的 testInstanceMethod() ,结果打印的是Cat,为什么呢?原因是父类的实例方法 被复写了 。只要他是子类的实例,调用实例方法只会得到子类的 复写方法

  • 总结

    父类的实力方法 父类的静态方法 子类的实例方法 Overrides(复写) Generates a compile-time error 子类的静态方法 Generates a compile-time error Hides(隐藏)

我相信有同学会问:那有没有什么法子调用父类的实例方法呢?答:有,那就是 super 关键字!

super关键字

废话少说,看代码:

public class Superclass {
    String name = "parent";
    public Superclass(String name){
        this.name = name;
    }
    public void printMethod() {
        System.out.println("Printed in Superclass.");
    }
}

public class Subclass extends Superclass {
    String name = "son";
    String id = "unique";
    public Subclass(String name,String id){
        super(name); //这里我们调用了父类的构造方法
        this.id = id;
    }
    // overrides printMethod in Superclass
    public void printMethod() {
        super.printMethod(); //这里我们调用了父类的 printMethod方法!
        System.out.println("Printed in Subclass.");
        System.out.println("My name is: "+name+". My id is: "+id);
    }
    public static void main(String[] args) {
        Subclass s = new Subclass("son","1234");
        s.printMethod();
    }
}

我们得到如下结果:

Printed in Superclass.
Printed in Subclass.
My name is: son. My id is: 1234

我们可以看到,我们使用了 super 关键字来调用 父类的 printMethod 方法。

那么 super还能干吗呢,我们还可以用super来调用 父类的构造方法。

我们看到这行代码:

public Subclass(String name,String id){
        super(name);
        this.id = id;
    }

其中的 super(name); 就调用了父类的构造方法,复用了代码,减少冗余代码。十分方便!

注意:如果我们没有在第一行写 super语句,编译器会自动调用父类的 无参构造方法

如果你的父类没写无参构造方法,编译器会报错!

多态

字典中的多态性的定义是指生物学中的一种原理,其中生物或物种可以具有许多不同的形式或阶段。 该原理也可以应用于面向对象的编程和Java语言之类的语言。 一个类的子类可以定义自己的独特行为,但也可以共享父类的某些相同功能。

class Animal {
    public void talk(){
        System.out.println("I am Animal!");
    }
}
class Cat extends Animal {

    public void talk() {
        System.out.println("I am Cat!");
    }
}
class Dog extends Animal {

    public void talk() {
        System.out.println("I am Dog!");
    }

    public static void main(String[] args) {
        Animal animal = new Animal();
        Cat cat = new Cat();
        Dog dog = new Dog();
        
        animal.talk();
        cat.talk();
        dog.talk();
    }
}

代码运行结果:

I am Animal!
I am Cat!
I am Dog!

多态是指由于继承和重写机制,相同类型的对象调用相同的方法,得到的结果可能不一样。

在前面的例子中 Dog 对象和 Cat 对象我们都可以认为是 Animal 对象,他们都在调用talk()方法,但是结果可能不一样,这是因为每个子类对象都可能会重写了这个方法。

结语

今天的文章就讲到这里,如果大家想了解更多关于 继承 的知识可以翻阅 Java 的 官方文档

祝大家生活愉快!LOL


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK