第十三讲 继承
1 面向对象三大特征
面向对象三大特征:
封装
继承
多态
关于封装:
类就是一种封装。以前学习C,数据和方法都是暴露在外面的。C也有封装,比如结构体。其实结构体就是类的原型。
类是一种封装,它将这一类事物的共有的属性和方法封装在一起。
比如:我们的手机,你需要知道实现的原理吗?你只要知道怎么用就行。这就是一种封装。它屏蔽了复杂的实现过程,给用户提供了简单的操作入口。比如手机不要外壳,不封装,那么里面的重要的元器件都暴露在用户面前,这样很危险。
封装确保了数据的安全,使得数据更加私密。使用者不需要直接操作数据,只要使用开发者提供的界面(接口)就可以了。
比如:芯片,国产芯片始终没有达到世界领先的水平,那么就需要向国外购买,国外的公司卖给我们的是一个完整的产品,不会给我们制作的方式方法,技术层面是被封装了,被屏蔽了,确保他们技术的安全性。
我们在写javabean的时候,见过封装。比如get、set方法(getter and setter)。比如overload,只给用户提供一个方法,和传入方法参数的规范,用户就可以操作。
封装的案例如下:
public class Chinese
{
private int id;
private String name;
private static String country = "China" ;
public Chinese ( ) { }
public Chinese ( Chinese this , int id, String name) {
this . id = id;
this . name = name;
}
public void setId ( int id) {
this . id = id;
}
public int getId ( ) {
return this . id;
}
public void setName ( String name) {
this . name = name;
}
public String getName ( ) {
return this . name;
}
public String toString ( ) {
return "[ " + id + ", " + name + " ]" ;
}
}
public class Test {
public static void main ( String[ ] args) {
Chinese c = new Chinese ( ) ;
c. getId ( ) ;
c. setId ( ) ;
System. out. println ( "fawefwe" ) ;
}
}
2 继承
继承:extends
什么是继承?为什么要继承?
继承:
在java中的继承跟我们在现实中的继承一样。我继承我父亲的财产,我继承我父亲的性格,我继承我祖辈的基因。
我们可以看到,我继承我父亲的基因,是不是表示我的基因是我父亲的。我继承我父亲的财产,是不是就是说我的这部分财产是我父亲的。
继承又可以表示为:is-a的关系。是一个。
比如:
Animal
Cat: Cat is an Animal
Dog: Dog is an Animal
Person:
ZhangSan is a Person
为什么要继承?
public class Animal
{
private String name;
private String type;
public void eat ( ) {
}
public void sleep ( ) {
}
}
public class Dog
{
private String name;
private String type;
public void eat ( ) {
}
public void sleep ( ) {
}
}
public class Cat
{
private String name;
private String type;
public void eat ( ) {
}
public void sleep ( ) {
}
}
上面的代码基本一致,基本重复,这样写下去太过于冗余。
java给我们提供了一个继承的机制。可以解决这种冗余。
语法:
父类:
public class Animal{}
子类:
public class Dog {}
我们希望子类和父类建立起继承的关系:使用关键字 extends
public class Dog extends Animal {}
public class Animal
{
private String name;
private String type;
public void setName ( String name) {
this . name = name;
}
public String getName ( ) {
return this . name;
}
public void eat ( ) {
System. out. println ( "eating" ) ;
}
public void sleep ( ) {
System. out. println ( "sleeping" ) ;
}
}
public class Dog extends Animal
{
}
public class Cat extends Animal
{
}
public class ExtendsTest
{
public static void main ( String[ ] args)
{
Dog dog = new Dog ( ) ;
dog. eat ( ) ;
dog. setName ( "哈巴狗" ) ;
System. out. println ( dog. getName ( ) ) ;
Cat cat = new Cat ( ) ;
cat. setName ( "醉猫" ) ;
System. out. println ( cat. getName ( ) ) ;
}
}
从上面代码中可以看出,使用继承以后,解决了代码的冗余。
从上面的代码中分析:
首先子类继承了父类。
继承了哪些内容:
继承了成员属性
继承了成员方法(不包括被private修饰的)
也继承了静态方法(不包括被private修饰的)
父类中private修饰的方法是父类独有的,不会被继承。
继承中的一个关系问题:
父类的引用指向子类的对象:这是可以的,这可以说Dog是Animal
子类的引用指向父类的对象:这是不可以的,这可以说Animal是Dog,显然不对。
构造方法被继承了吗?
假如构造方法被继承了。
那么如果在父类中有一个无参数的构造方法,在子类中没有无参数的构造方法,是可以构造子类对象的。
如果父类的构造方法被子类继承了,那么就可以实现子类的引用指向父类的对象。
因为子类拥有父类的构造方法,Dog dog = new Animal();
从实验中我们可以看到构造方法并没有被继承。
public class Animal
{
private void run ( ) {
System. out. println ( "running" ) ;
}
}
public class Cat extends Animal {
}
public class ExtendsTest
{
public static void main ( String[ ] args)
{
Cat cat = new Cat ( ) ;
cat. run ( ) ;
}
}
public class Animal
{
private String name;
private String type;
public Animal ( ) { }
public Animal ( String name, String type) {
this . name = name;
this . type = type;
}
public void setName ( String name) {
this . name = name;
}
public String getName ( ) {
return this . name;
}
public void eat ( ) {
System. out. println ( "eating" ) ;
}
public static void sleep ( ) {
System. out. println ( "sleeping" ) ;
}
public void run ( ) {
System. out. println ( "running" ) ;
}
}
public class ExtendsTest
{
public static void main ( String[ ] args)
{
Dog dog = new Dog ( ) ;
dog. eat ( ) ;
}
}
3 进一步了解继承
子类继承父类,拥有父类的属性和方法(非private修饰的)。
private的属性子类无法直接访问,但可以通过方法父类提供的方法间接的访问。
父类的能力是有限的,子类拥有了父类的一些方法和属性之后,还可能满足不了需求。
比如: Animal这个父类中,有eat() sleep() run()
但是Dog这个子类,它有它自己的特有的行为。
比如:狗会摇尾巴。Dog类要有一个waveTail()方法。
我们应该怎么做呢?
在子类中定义。
为什么可以这样呢?
因为青出于蓝而胜于蓝。
也就是说,在子类中可以定义很多子类特有的行为和属性。这些方法和属性是父类没有的,可以在子类中进行定义。
(记住)一个父类可以有很多子类,但是一个子类只能有一个父类。java中不能多继承,只能继承一个父类。
如果一个类没有通过extends继承任何类,实际上它也继承了一个老祖宗类,这个类的名字叫做Object;
继承是可以传递的,可以从A继承B继承C继承D,这样是可以的。
A extends B {}
B extends C {}
C extends D {}
D的级别是最高得
C拥有D的属性、方法(非private),
B拥有C和D的属性和方法(非private)
A拥有BCD的属性、方法(非private)。
我们看得出来:子类的能力要比父类强大。父类一旦被定义,子类一旦继承,父类除了private的方法之外,其他的基本上被子类所有。
继承这种机制,父类其实是一个抽象,是子类共性的集合。或者是说父类是子类共有属性和方法的一个集合。是子类共有属性、方法的模板。
有了继承之后,好处很多,比如减少代码的冗余。但这不是最主要的功能。
最最重要的功能是为多态提供了实现的可能。
public class Dog extends Animal
{
public void waveTail ( ) {
System. out. println ( "摇尾巴!!" ) ;
}
}
public class ExtendsTest
{
public static void main ( String[ ] args)
{
Dog dog = new Dog ( ) ;
dog. eat ( ) ;
dog. setName ( "哈巴狗" ) ;
dog. waveTail ( ) ;
System. out. println ( dog. getName ( ) ) ;
dog. sleep ( ) ;
Dog. sleep ( ) ;
dog. sleep ( ) ;
Cat cat = new Cat ( ) ;
cat. setName ( "醉猫" ) ;
System. out. println ( cat. getName ( ) ) ;
cat. run ( ) ;
Animal a = new Dog ( ) ;
}
}