关闭

面向对象6——继承

257人阅读 评论(0) 收藏 举报
分类:

继承:

好处:

1,继承的出现,提高了代码的复用性。

2,继承的出现,让类与类之间产生了关系。而这个关系出现,就导致面向对象的第三个特征,多态的产生。

简单说:继承就是多态的前提。

Java中支持单继承,不支持多继承(其实更确切的说,是java将多继承进行改良,避免了安全隐患的产生)

class A{void show(){System.out.println("a");}

class B{}{void show(){System.out.println("b");}

class C extends A,B{}//这就是多继承,一个子类同时有多个父类。在java中是允许的。

C c = new C();

c.show();//到底是运行a,还是运行b呢?所以这就是安全隐患。为了避免,所以java支持这样继承。

简单说:一个儿子只能有一个爹,不能同时有多个爹。

Java中可以存在多层(多重)继承。

class A{}

class B extends A{}

class C extends B{}

这时就出现了继承体系。

记住一个原则:

1A类中定义是这个体系中的最共性的功能。

2,要使用这个体系的功能,建议建立最子类的对象来完成调用。

父类的由来都是子类不断向上抽取而来的。

就代表着,A中定义的功能是该体系中最共性的功能。

所以要了解这个体系的功能,只要参考A类中的功能即可。

了解后,需要建立对象来调用这些功能,那么建立哪个类的对象好呢?

建议建立C的对象,因为C中可以使用A类中的共性功能,也可以使用C类中的特有功能。

简单说:

要使用一个继承体系,原则:

1,参阅父类功能,

2,建立最子类对象。

什么时候定义继承呢?

继承是用于程序设计的。

只要一个事物是另一个事物的一种。就可以用继承体现。

猫或者虎都是猫科这类事物中的一种。就是可以进行继承。

狗或者狼都是犬科,也可以继承。

猫科,犬科,都是哺乳动物中的一种。也可以进行继承。

简答的分析:怎么判断是另一个事物的中的一种呢?

那么可以先视为可以继承,用更简单的方式判断,一个类如果继承了另一个类,那么这个类是否应该具备另一个类的所有的成员。如果可以。继承有效,如果不可以,那么无法继承。

注意的是:不要为了获取另一个类中的部分功能,而继承。这样是仅仅为了提高复用性而继承,并没有判断事物之间的关系。这样不可取。

class A

{

void method1(){}

void method2(){}

}

class B //extends A//如果为了提高复用,让B继承A这样,B就不用在定义method1()方法了,

//但是B也获取到它不应该具备的method2().

//那么这样的继承不可以存在。

//但是我们发现,虽然AB之间没有继承关系,但是他们有共性的内容,

//那么就可以向上抽取。。

{

void method1(){}

void method3(){}

}

class C

{

void method1(){}

}

class A extends C

{

void method2(){}

}

class B extends C

{

void method3(){}

}

*/

class Person

{

String name;

int age;

}

继承出现后,在子父类中的成员特点。

成员:

成员变量。

成员函数。

构造函数。

//在子父类中成员变量的特点。

当子父类中出现同名的成员变量时,

这是为了区分两个变量,

在子类,用this调用的是子类的变量。

super调用的是父类中的变量。

super其实和this的用法很相似。

this代表是本类对象的引用

super代表的是父类的存储空间。

this可以区分局部变量和成员变量重名的情况。

super可以用于区分子父类中成员变量重名的情况。

这个部分作为了解。这是引出一个关键字super

不是重点,因为,属性在类中通常都是私有的,而且父类定义完了以后,

子类一般是不会定义同名变量的。而是直接使用父类的变量即可

所以开发并不常见。而面试却很常见。

注意:在访问上,子类不可以直接访问父类中的私有成员。

  可以通过间接的形式访问。

子父类中成员函数的特点:

特殊情况:

当子父类中出现一模一样的函数时,

子类对象在调用该函数时,运行的是子类中的函数。

父类中的函数好像被覆盖一样。

这就是函数的另一个特性:覆盖(复写,重写)override 函数的另一个特性: 重载 overload

覆盖:在子父类中,如果出现一模一样的函数时,就会发生覆盖操作。

子父类中的构造函数的特点:

通过结果发现,子类的构造函数运行前,父类的构造函数先运行了?

为什么呢?

原因在于在子类的构造函数的第一行,其实就一条默认的隐式语句 super();

super():this():用法是一样的。

this();调用了本类中的构造函数。

super():调用了父类中的构造函数。

子类的构造函数中为什么都有一个默认的super()语句呢?

子类在实例化的时候,因为子类继承了父类的成员数据,

所以必须要先看父类是如何对自己的成员进行初始化的。

#################################################################

#子类的所有构造函数默认都会访问父类中空参数的构造函数。 #

#当父类中没有定义空参数的构造时, #

#子类必须通过super语句或者this语句 #

#明确指定要访问的子类中或者父类中的构造函数。 #

# #

#简单说:子类的构造函数无论如何,都必须要访问父类中的构造函数。 #

#要明确父类的初始化过程. #

#################################################################

super语句用于访问父类的初始化,而初始化动作要先完成,所以super语句必须定义在构造函数的第一行。

那么就和曾经的this语句冲突了。因为this语句也要定义在构造函数的第一行。

所以一个构造函数中,只能有一个要么this语句,要么super语句。

而且不冲突,因为子类中至少会有一个构造函数回去访问父类中的构造函数。一样可以完成父类的初始化。

这个就是子类的实例化过程。

继承的弊端:打破的封装性。

如果恶意继承并进行不正确的覆盖,会导致原功能的错误。打破了封装性。

不让其他类继承可以解决这个问题。

这就需要一个关键字来完成 :final(最终)

final:作为一个修饰符。

1,它可以修饰类,可以修饰方法,可以修饰变量。

2final修饰的类是一个最终类,不可以被继承。

3final修饰的方法不可以被覆盖。

4final修饰的变量的是一个常量,只能被赋值一次。这个赋值指的是显示初始化赋值。 

什么时候将变量修饰成final的呢?

通常在程序中会使用一些不会变化的数据。也就是常见的一些常量值。比如 3.14

那么这个数据直接使用是可以的,但是不利于阅读,所以一般情况下,都会被该数据起个容易阅读的名称。

final double PI = 3.14;

final修饰的常量定义一般都有规范书写,被final修饰的常量名称,所有字母都大写。

如果由多个单词所组成,每一个单词间用_连接。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:17628次
    • 积分:562
    • 等级:
    • 排名:千里之外
    • 原创:39篇
    • 转载:5篇
    • 译文:0篇
    • 评论:0条
    文章分类