书接上回, 我们之前谈过了类和对象的概念, 今天我来讲一讲面向对象程序设计的另外一个基本概念 - 继承
目录
为什么需要继承
自动转型与强制转型
继承能干啥
复写和隐藏
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. 再分别调用它的静态方法和实例方法.
结果如下:
第一行, 我们用 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
来源: https://www.cnblogs.com/jiaweixie/p/12538901.html