首页 > 代码库 > 继承简介
继承简介
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。继承可以理解为一个对象从另一个对象获取属性的过程。
如果类A是类B的父类,而类B是类C的父类,我们也称C是A的子类,类C是从类A继承而来的。在Java中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类
继承中使用的关键字是extends。类的继承决定了一个对象和另一个对象是否是IS-A(是一个)关系。通过继承,我们能实现一个对象获取另一个对象的属性。
一、继承
通过上面的概述,已经知道了继承,下面通过Code来分析继承:
Animal类:(祖父类) public class Animal { public String name = "Animal, 多态成员变量测式,父类对象"; public void show() { System.out.println("动物....(祖父类)"); } public void eat() { System.out.println("动物吃东西....(祖父类)"); } public void sleep() { System.out.println("动物睡觉....(祖父类)"); }}Mammal类:(父类) public class Mammal extends Animal { public String name = "Mammal Animal"; public void fight() { System.out.println("哺乳动物喜欢打架吗?...(添加新的功能)"); } public void fly(){ System.out.println("哺乳动物会飞吗?...(添加新的功能)"); } //测试私有是否可以继承 private void test() { System.out.println("private..."); } //测试保护是否可以继承 protected void test(int a) { System.out.println("protected...(被访问了)"); } //测试保护是否可以继承 void test(char c) { System.out.println("default...(被访问了)"); }}Cat类:(子类) public class Cat extends Mammal{ public String name = "Cat"; public void show() { System.out.println("猫...(对父类的重写)"); }}Dog类:(子类) public class Dog extends Mammal{ public String name = "Dog,验证变量的多态"; public void show() { System.out.println("狗...(子类对父类的重写)"); } public void sleep(){ System.out.println("狗睡觉...(子类对父类的重写,验证方法的 多态)"); }}ExtendsDemo类:(测试类) public class ExtendsDemo { public static void main(String[] args) { // 验证继承性 System.out.println("@@@@@@@@@ 验证继承性: @@@@@@@@@"); Dog dog = new Dog(); dog.eat(); // 测试继承的权限 System.out.println("\n\n@@@@@@@@@ 测试继承的权限: @@@@@@@@@"); Cat cat = new Cat(); // 私有的不能访问 // cat.test(); // 保护和默认的都可以 cat.test(‘c‘); cat.test(1); // 子类添加新的功能 System.out.println("\n\n@@@@@@@@@ 子类添加新的功能: @@@@@@@@@"); Mammal mammal = new Mammal(); mammal.fight(); mammal.fly(); // 验证重写 System.out.println("\n\n@@@@@@@@@ 验证重写: @@@@@@@@@"); Animal animal = new Animal(); animal.show(); dog.show(); // 验证多态性 System.out.println("\n\n@@@@@@@@@ 验证多态性: @@@@@@@@@"); // 成员变量的多态验证 Animal animal2 = new Dog(); System.out.println(animal2.name); System.out.println("成员变量的多态,编译看左边,运行也看左边, 也就是调用的是父类的成员变量\n\n"); // 成员方法的多态验证 animal2.sleep(); System.out.println("成员方法的多态,编译看左边,运行也看右边, 也就是调用的是子类的成员方法"); }}
测试截图:
- 继承的父类、子类
- 超类:被继承的类叫做超类(父类)。也就是已经存在的类且被定义在某个类的extends关键词后面的类叫做父类
- 子类:继承的类叫做子类(基类)。也就是通过超类派生的类
- 继承的权限
- 被private修饰的成员方法和成员变量不能被继承
- 被public,protected和默认修饰的成员方法和成员变量能被继承
- 通过继承子类可以得到超类的非private修饰的方法,如上面Code中的:dog.eat();
在Dog类中并没有eat()方法,但是却可以调用,是因为Dog继承自Animal,得到了Animal的eat()方法
- 通过继承也可以得到超类非private修饰的成员变量
- super关键字 :和this相对,this表示本身对象,而super则是代表超类对象。
public Dog() { super(); //调用父类的构造}public void sleep() { System.out.println("狗睡觉...(子类对父类的重写,验证方法 的多态)"); super.fly(); //调用父类的方法 }
- super和this的总结:
- this的三个用途:
- 引用隐式参数
- 调用该类的其他构造器
public Dog() { this("this测试");}public Dog(String name) { super(); this.name = name;}
- 调用该类的方法
- super的两个用途:
- 调用超类的方法
- 调用超类的构造器
- 如果子类没有显示的调用超类的构造器,则将自动调用超类的默认构造器。如果超类没有不带参数的构造器,并且子类构造器中由没有显示的调用超类的其他构造,那么Java编译器将报错。
- 继承层次:
对于上面的程序示例,Animal派生Mammal,Mammal派生Dog和Cat,这些继承关系之间就组成了一个层次关系。
由一个公共超类派生出的所有类的集合被称为继承层次。在继承层次中,从某个特定的类到其祖先的路径被称为继承链。
图解:
二、多态和重写(覆盖)
多态是对象采取多种形式表现的能力。当一个父类引用是用来指向一个子类对象时,在通过父类对象去调用子类的方法,就是一个多态表现。
- 多态存在的条件
- 继承:多态的存在必须要继承
- 重写父类方法:除了继承外,多态还要重写父类的方法
- 多态是什么?
多态是指当父类和子类都有同样的方法的时候,且父类对象变量引用了子类的对象,那么在调用的时候,就会动态的绑定到具体的子类,然后在调用子类的这个方法,而不是因为是父类的对象变量就调用父类的方法。
所以有了a)的两点条件,解释一下:
- 继承:因为要父类对象去引用子类的对象,所以要有继承
- 重写:因为要有和父类同样的方法,那么这个方法就是继承去的,所 以为了体现不同,最好重写,不然这种多态是无意义的。
- 多态的实现机制:动态绑定(下面介绍)
- 多态的三点重点:
成员变量的多态:编译看左边(看父类),运行看左边(看父类), 所以调用的还是父类的成员对象。
静态方法的多态:编译看左边(看父类),运行看左边(看父类), 所以调用的还是父类的静态方法。
成员方法的多态:编译看左边(看父类),运行看右边(看子类), 所以调用的是子类的成员方法。
- 构造方法的调用:
在创建子类对象的时候,同时还会调用父类的构造方法,对父类数据进行初始化。
- 多态的优点
- 提高了代码的维护性
- 提高了代码的扩展性
三、绑定
程序绑定的概念:绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。对java来说,绑定分为静态绑定和动态绑定;或者叫做前期绑定和后期绑定
- 静态绑定
在程序执行前方法已经被绑定,此时由编译器或其它连接程序实现。例如:C。针对java简单的可以理解为程序编译期的绑定;这里特别说明一点,java当中的方法只有final,static,private和构造方法是前期绑定
- 动态绑定
后期绑定:在运行时根据具体对象的类型进行绑定。若一种语言实现了后期绑定,同时必须提供一些机制,可在运行期间判断对象的类型,并分别调用适当的方法。也就是说,编译器此时依然不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。不同的语言对后期绑定的实现方法是有所区别的。但我们至少可以这样认为:它们都要在对象中安插某些特殊类型的信息。
动态绑定的过程:
1. 虚拟机提取对象的实际类型的方法表;
2. 虚拟机搜索方法签名;
3. 调用方法。
四、阻止继承
在实际的开发中可能不允许某个类定义子类,那么这种类叫做最终类或者叫做final类。但这个final类如何实现呢?见下代码就是一个final类:
final public class Person extends Mammal{ private String name; private String gender; private int age; public Person(){} public Person(String name,String gender, int age){ super(); this.name = name; this.age = age; this.gender = gender; } ....}
扩展知识点:
- instanceof关键字
java中的instanceof运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。
if (dog instanceof Animal) { System.out.println("dog是Animal类的一个实例");} else { System.out.println("dog不是Animal类的一个实例");}if (animal instanceof Dog) { System.out.println("animal是Dog类的一个实例");} else { System.out.println("animal不是Dog类的一个实例");}
当将超类转成子类之前一定要使用instanceof对子类对象进行检查。如下代码段:
Animal animal = new Dog();if (animal instanceof Dog) { Dog dog = (Dog)animal; System.out.println("animal是Dog类的一个实例,可以转 换");}else { System.out.println("animal不是Dog类的一个实例");}
- 受保护的访问
受保护的访问就是对protected修饰的方法和成员变量的访问。访问权限见总结12
- final修饰符(重点)
- final修饰变量:那么变量变为常量,在赋初值之后,值不可以在改变
- final修饰类:那么类就变为最终类,不可在派生子类
- final修饰方法:则该方法可以被继承,但是不可以被重写。
- final修饰对象:那么对象的引用不可再变,但是引用对象的值是可以变的。(就 是说对象被final修饰后,就不能在指向其他的对象,但是对 象中存储的值是可以变的)
继承简介