您的位置:首页 > 职场人生

黑马程序员——面向对象(继承)-第17天

2015-09-03 16:51 573 查看


----------- android培训java培训java学习型技术博客、期待与您交流! ------------

面向对象(继承)

1、面向对象(继承-概述)

//定义一个学生

class Student

{

String name;

int age;

void study()

{

system.out.println("study");

}

}

//定义一个工人

class Worker

{

String name;

int age;

void work()

{

system.out.println("work");

}

}

我们想把上面俩个类中的name和age共性的内容抽取出来。单独进行描述。

只要让学生和工人与单独描述的这个类有关系。

class Person

{

String name;

int age;

}

class Student extendsPerson//子类Student继承父类Person

{

void study()

{

system.out.println("study");

}

}

class Worker extends Person

{

void work()

{

system.out.println("work");

}

}

继承:

1,提高代码的复用性。

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

注意:千万不要为了获取其他类的功能,简化代码而继承。

必须是有类与类之间有所属关系。才可以继承。

2、面向对象(继承-概述2)

class C

{

void demo1(){}

}

class A extendsC

{

//void demo1(){}

void demo2(){}

}

class B extendsC

{

//void demo1(){}

void demo3(){}

}

A和B都可以继承C。先有父类。然后子类再引用。

Java语言中:java只支持单继承,不支持多继承。

因为多继承容易带来安全隐患。当多个父类的功能相同,但是内容不同,不确定要运行哪一个。但是java保留了这种机制。通过:"多实现"完成。

class A

{

void show()

{

system.out.println("a");

}

class B

{

void show()

{

system.out.println("b");

}

}

class C extends A,B//多继承

{

C c=new C();//这样就不确定打印的是A,还是B.

c.show();

}

java支持多层继承(嵌套继承,C继承B,B继承A,),也就是一个继承体系。

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

想要使用体系,先查阅体系父类的描述。因为父类定义的是该体系中的共性内容。

通过了解共性功能,就可以知道该体系的基本功能。

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

1,可能父类不能创建对象。

2,创建子类对象可以使用更多的功能,包括基本的(父类)也包括特有的。

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

3、面向对象(子父类中变量的特点)

子父类出现后,类成员的特点:

类中成员:

1,变量

2,函数

3,构造函数

class Fu

{

int num1=4;

}

class Zi extends Fu

{

int num2=5;

}

class ExtendsDemo2

{

public static void main(String[] args)

{

Zi z=new Zi();

}

system.out.println(z.num1+"..."+z.num2);//打印4...5

对比:子类和父类的变量名相同是:

class Fu

{

int num=4;

}

class Zi extends Fu

{

int num=5;//先加载父类的num=4;然后子类的变量num=5覆盖了父类

}

class ExtendsDemo2

{

public static void main(String[] args)

{

Zi z=new Zi();

system.out.println(z.num+"..."+z.num);//打印5...5。打印的是子类num。

}

如果要打印Fu类中的内容时,用super变量。

class Fu

{

int num=4;

}

class Zi extends Fu

{

int num=5;

void show()

{

system.out.println(super.num);//super代表父类的引用。

}

}

class ExtendsDemo2

{

public static void main(String[] args)

{

Zi z=new Zi();

z.show();//打印4

}

如果子类出现非私有的同名成员变量时

1,访问本类中的变量,用this

2,访问父类中的变量,用super

5、面向对象(子父类中函数的特点-覆盖)

子父类中函数的特点:

当子类出现和父类一样的函数时:

当子类对象调用该函数,会运行子类函数的内容。

如同父类的函数被覆盖一样。

这是函数的一个特性:重写(覆盖)

class Fu

{

void show()

{

system.out.println("fu");

}

}

class Zi extends Fu

{

void show()

{

system.out.println("zi");

}

}

class ExtendsDemo2

{

public static void main(String[] args)

{

z.show();//打印zi。运行的是子类的内容。

}

当子类继承父类,沿袭父类的功能,到子类中。

但是子类已经具备该功能了,但是功能的内容却和父类不一致。

这时,没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义,并重写功能的内容。

class Fu

{

void show()

{

system.out.println("fu");

}

void speak()

{

system.out.println("vb");

}

}

class Zi extends Fu

{

void speak2()

{

system.out.println("java");

}

void show()//覆盖了父类的

{

system.out.println("zi");

}

}

class ExtendsDemo2

{

public static void main(String[] args)

{

z.show();//打印zi。运行的是子类的内容。

}

例如:

老手机的功能:

class Tel

{

void show()

{

system.out.println("number");

void lingsheng(){}

}

新手机继承老手机:

class NewTel extendsTel

{

void show()

{

system.out.println("number");//覆盖了父类的内容。

system.out.println("name");

system.out.println("pic");

}

改进新手机

class NewTel extends Tel

{

void show()

{

super.show();//用super引用父类。

system.out.println("name");

system.out.println("pic");

}

覆盖:

1,子类覆盖父类,必须保证子类权限>=父类,才可以覆盖,否则编译失败。

2,静态只能覆盖静态。(因为加载问题,非静态只有调用的时候才加载。)

3,权限从大到小:public>void(一般)>private

class Tel

{

void show()

{

....

}

class NewTel extends Tel

{

private void show()//编译错误。

{

......

}

下面这种情况不叫覆盖。

class Tel

{

private void show()//父类私有化。子类不知道有这个东西。

{

....

}

class NewTel extends Tel

{

voidshow()//编译错误。

{

......

}

记住:

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

重写(覆盖):子父类方法要一模一样。

6、面向对象(子父类中构造函数的特点-子类实例化过程)

class Fu

{

Fu()//父类的构造函数,随着类名走。

{

system.out.println("fu run");

}

}

class Zi extendsFu

{

Zi()

{//super();虚拟机默认自动加在第一行,而且是隐藏起来的。可以不写,也可以写上。调用父类,故先打印父类。

system.out.println("zi run");

}

}

class ExtendsDemo2

{

public static void main(String[] args)

{

Zi z=new Zi();

}//打印:

fu run

zi run

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

因为子类的构造函数的第一行有一条隐藏式的语句super();

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

改成下面的值,也是没有影响的。

class Fu

{

Fu()

{

system.out.println("fu run");

}

Fu(int x)//它不影响空参数构造函数

{

system.out.println("fu...");

}

}

class Zi extends Fu

{

Zi()

{

system.out.println("zi run");

}

}

class ExtendsDemo2

{

public static void main(String[] args)

{

Zi z=new Zi();

}

但是:如果父类没有空参数构造函数的话呢?

class Fu

{//没有

Fu(int x)

{

system.out.println("fu run");

}

}

class Zi extends Fu

{

Zi()

{

system.out.println("zi run");

}

}

class ExtendsDemo2

{

public static void main(String[] args)

{

Zi z=new Zi();//编译报错。这时系统不会自动创建空参数构造函数

}

这时,需要手动设置super()的值,让它指向父类。

class Fu

{

Fu(int
x)

{

system.out.println("fu run");

}

}

class Zi extends Fu

{

Zi()

{

super(4);

system.out.println("zi run");

}

}

class ExtendsDemo2

{

public static void main(String[] args)

{

Zi z=new Zi();//编译通过。

}

另外可以用this(),指向子类

class Fu

{

Fu(int x)

{

system.out.println("fu run");

}

}

class Zi extends Fu

{

Zi()

{

system.out.println("zi run");

}

Zi(int x)

{

this();//这时super()不存在。

system.out.println("zi run");

}

}

class ExtendsDemo2

{

public static void main(String[] args)

{

Zi z=new Zi(0);//编译通过。

}

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

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

所以子类在对象初始化时,要先访问一下父类中的构造函数。

需要访问父类中指定的构造函数,可以手动方式来定义。

class Person

{

private String name;

Person(String name)//提供name的访问方法

{

this.name=name;

}

}

class Student extends Person

{

Student(String name)

{

super(name);//直接拿来用就行了。



}

结论:子类的所以构造函数,默认都会访问父类中空参数的构造函数。因为子类有super()

当父类中没有空参数的构造函数时,子类必须手动通过super调用。

当然:子类的构造函数第一行也可以手动指定this访问本类的构造函数。

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

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

class Fu//这里也会默认为classFu extends object。继承最基本的对象

{

//这里默认也会有个super();

Fu()

{

system.out.println("fu run");

}

Fu(int x)

{

system.out.println("fu run");

}

}

class Zi extends Fu

{

Zi()

{

问题明确下:

为什么this和super不能在同一行?(不能同时在构造函数当中)

因为他们都只能写在第一行。

为什么写第一行?

因为初始化动作要先做。

system.out.println("zi run");

}

Zi(int x)

{

this();

system.out.println("zi run");

}

}

class ExtendsDemo2

{

public static void main(String[] args)

{

Zi z=new Zi(0);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: