黑马程序员------毕老师视频笔记第七天------面向对象(继承)

来源:互联网 发布:索尼kdl55r580c装软件 编辑:程序博客网 时间:2024/05/18 17:00

---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------

一.继承概述

class Person{String name;int age;}class Student extends Person{void study(){System.out.println("good study!");}}class Worker extends Person{void work(){System.out.println("I'm working~");}}

将对象的共性的属性抽取出来,就得到了类,将几个类中的共性内容抽取出来,得到了父类。

继承:

①提高了代码的复用性

②继承让类与类之间产生了关系,有了这个关系才有了多态的特性

 

注意:千万不要为了获取其他类的功能,简化代码而继承,必须是类与类之间有所属关系才可以继承,所属关系 is a .谁是谁中的一员。

 

在java中,只支持单继承,不支持多继承(不严谨)。

多继承容易带来安全隐患,当多个父类中定义了相同的功能,当功能内容不同的时候,子类继承过来之后调用该名称的方法时不知道调用哪个。

优化了c++,c++支持多继承

但是java保留了这种机制,并用另一种体现形式来完成表示,叫做:多实现。

所以准确的说,java只是改良了多继承。

 

java支持多重继承,也就是一个继承体系

如何使用一个继承体系中的功能呢?

想要使用体系,先查阅体系中父类的描述,因为父类中定义的是体系中的共性功能,通过了解共性功能,就可以了解该体系的基本功能,那么这个体系已经可以基本使用了。

那么在具体调用时,要创建最子类的对象,为什么呢?

①有可能父类不能创建对象,如抽象类

②创建子类对象可以使用更多的功能,有共性的,也有特有的。

简单一句话就是,查阅父类功能,创建子类功能使用对象。


二.子父类中变量的特点

class Fu{int num = 4;}class Zi extends Fu{int num = 5;void show (){System.out.println(num+"..."+this.num+"..."+super.num);}}class ExtendsDemo{public static void main (String [] args){Zi z = new Zi();z.show();}}


*子类父类中变量名相同的变量,直接使用的是子类的变量,因为省略了this(本类对象的引用),要想使用父类中相同名称的变量,要用super (父类对象的引用)。

super的使用和this 基本一样。

 

有了继承关系以后,对象在内存中的加载会出现一些变化,new Zi语句执行的时候,会在内存中开辟两片空间,先加载父类变量,后加载子类变量。super是父类的引用,this是子类的引用,但是,上面的例子中,如果子类中没有num变量会怎么样呢?

class Fu{int num = 4;}class Zi extends Fu{//int num = 5;void show (){System.out.println(num+"..."+this.num+"..."+super.num);}}class ExtendsDemo{public static void main (String [] args){Zi z = new Zi();z.show();}}

子类中没有num,num前省略的是super,super.num是4好理解,可是怎么理解this.num也是4呢?

理解一:Zi继承了Fu之后,Zi中就有了一个num=4,所以this.num的值就是4

理解二:父类的引用指向了子类的对象,这里只有一个对象,new Zi(),this和super指向的其实都是这个对象


三.子父类中函数的特点---覆盖

如果子父类中的方法名一致会怎么样呢?

class Fu{void show(){System.out.println("Fu run");}}class Zi extends Fu{void show (){System.out.println("Zi run");}}class ExtendsDemo{public static void main (String [] args){Zi z = new Zi();z.show();}}


当子类出现和父类一模一样的函数的时候,当子类对象调用该函数,会运行子类的内容,如同父类的函数被覆盖一样

这种情况是函数的另外一种特性:重写(覆盖)

 

当子类继承父类,沿袭了父类的功能到子类中,但是子类虽具备该功能,但是功能的内容却和父类不一致,这时,没有必要定义新功能,而是使用覆盖特性。保留父类功能定义,重写子类功能。

提高了程序的扩展性,不用修改以前的源码。

 

注意:

①子类覆盖父类,必须保证子类权限大于等于父类权限,否则编译失败。

②静态只能覆盖静态

 

重载:只看同名函数的参数列表

重写:子父类方法要一模一样

 

四.子父类中构造函数的特点---子类实例化过程

class Fu{static {System.out.println("Fu class in~");}{System.out.println("Fu 构造代码块 run~");}Fu(){System.out.println("Fu 构造函数 run~");}}class Zi extends Fu{static {System.out.println("Zi class in~");}{System.out.println("Zi 构造代码块 run~");}Zi(){System.out.println("Zi 构造函数 run~");}}class ExtendsDemo{public static void main (String [] args){new Zi();}}

在子类对象进行初始化时,父类的构造函数也会运行

那是因为子类构造函数默认第一行有一条隐式语句 super();

它会访问父类中空参数的构造函数,而且子类中所有构造函数第一行默认都是super();

 

为什么子类一定要访问父类中的构造函数?

因为父类中的数据子类可以直接获取,所以子类在建立对象时,需要先查看父类是如何对这些数据进行初始化的。所以子类在对象进行初始化时,需要先访问一下父类中的构造函数。

如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。

 

注意:super(); 语句一定定义在子类构造函数的第一行。

因为this() 语句也只能放在构造函数的第一行,所以这两个语句只能有一个。

 

子类的所有构造函数,默认都会访问父类中空参数的构造函数,因为每一个子类的构造函数内的第一行都有一个隐式的super(); 当父类中没有空参数的构造函数时,子类必须手动通过super语句形式指定要访问的父类中的构造函数。当然,子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。

子类中至少有一个构造函数会访问父类中的构造函数。

 

父类中的构造函数第一行也有一个隐式的super();

java中有一个类是所有类的父类------object类


---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------

0 0
原创粉丝点击