书接上回,我们之前谈过了类和对象的概念,今天我来讲一讲 面向对象程序设计 的另外一个基本概念— 继承
我们先先念一遍定义:利用继承,人们可以基于已存在的类构造一个新类。继承已存在的类就是复用(继承)这些类的方法和属性。在此基础上,还可以添加一些新的方法和属性,以满足新的需求。这是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 关键字!
废话少说,看代码:
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