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

6--黑马程序员--技术总结之继承与接口

2015-05-08 21:41 253 查看
----------------------ASP.Net+Unity开发.Net培训、期待与您交流!
----------------------

一.继承
1.继承的概念

“继承”是Java面向对象中的一个重要概念。如果一个类A继承自另一个类B,就把这个A称为"B的子类",而把B称为"A的父类"。继承可以使得子类具有父类的各种属性和方法,而不需要再次编写相同的代码。在令子类继承父类的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类的原有属性和方法,使其获得与父类不同的功能。另外,为子类追加新的属性和方法也是常见的做法。继承的出现,可以提高代码的复用性,并且让类与类产生了关系,使得整个程序的联系更加紧密。

有些编程语言支持多重继承,即一个子类可以同时有多个父类,比如C++编程语言;而在Java中,一个子类只能继承自一个父类,这时可以利用接口来实现与多重继承相似的效果。我在本博客后面介绍接口。

2.继承的声明

我们之前定义类的时候,都是从头开始,详细的定义该类的每一个成员。比如下面的Human类:

[html] view
plaincopy





class Human { //定义父类

public int getHeight() { //定义getHeight方法

return this.height;

}

public void growHeight(int h) { //定义growHeight方法

this.height = this.height + h;

}

public void breath() { //定义breath方法

System.out.println("呼吸");

}

private int height;

}

从上面的类定义,我们可以了解该类的所有细节: 该类的数据成员,该类的方法,该类的接口。

现在要定义一个新的类,比如Woman类,并假设Woman与Human类相当类似:

设woman类有和Human类有两个相同的方法growHeight()和getHeight(),但它有一个自己的方法叫giveBirth().

我们可以像以前一样,从头开始,完整的定义Woman类:

[html] view
plaincopy





class Woman{ //定义Woman类

public int getHeight() { //和Human类相同的getHeight方法

return this.height;

}

public void growHeight(int h) { //和Human类相同的growHeight方法

this.height = this.height + h;

}

public void breath() { //和Human类相同的breath方法

System.out.println("呼吸");

}

public void giveBirth() { //自己独有的giveBirth方法

System.out.println("繁衍");

}

private int height;

}

而利用继承,我们可以避免上面的重复。让Woman类继承自Human类,Woman类就自动拥有了Human类中所有public成员的功能。

我们用extends关键字表示继承:

[html] view
plaincopy





class Woman extends Human {

public void giveBirth() {

System.out.println("繁衍");

}

}

这样,我们就省去了大量的输入。通过继承,我们创建了一个新类,叫做衍生类(derived class)。被继承的类(Human)称为基类(base class)。衍生类以基类作为自己定的基础,并补充基类中没有定义的giveBirth()方法。

3.成员变量的隐藏和方法的重写

那么你可能会问了,子类继承了父类后,想同时使用本类和父类的变量和方法要怎么做呢?这就涉及到了成员变量的隐藏和方法的重写。子类也可以隐藏继承的成员变量,对于子类可以从父类继承成员变量,只要子类中定义的成员变量和父类中的成员变量同名时,子类就隐藏了继承的成员变量,即子类对象以及子类自己声明定义的方法操作与父类同名的成员变量是指子类重新声明定义的这个成员变量。

子类可以隐藏已继承的方法,子类通过方法重写来隐藏继承的方法。方法重写是指:子类中定义一个方法,并且这个方法的名字、返回类型、参数个数和类型与从父类继承的方法完全相同。子类通过方法的重写可以隐藏继承的方法,子类通过方法的重写可以把父类的状态和行为改变为自身的状态和行为。如果父类的方法f可以被子类继承,子类就有权利重写f’一旦子类重写了父类的方法f,就隐藏了继承的方法f,那么子类对象调用方法f一定是调用重写的方法f,重写的方法既可以操作继承的成员变量也可以操作子类声明定义的成员变量。如果子类想使用被隐藏的方法,必须使用关键字super。如果子类想使用本类的方法,必须使用关键字this(this
和 super将在下篇博客重点介绍)。

下面举一个子类重写父类方法的例子

[html] view
plaincopy





public class ExtendsDemo2 {

/**子类重写父类方法

* @黑马ZWF

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

Xiangjia sum = new Xiangjia();

int c = sum.f(99,60);

System.out.println(c);

}

}

class Chengji {

int f(int x, int y) {

return x+y;

}

}

class Xiangjia extends Chengji {

int f(int x, int y) {

return x+y;

}

}

对于子类创建的一个对象,如果子类重写了父类的方法,则运行时系统调用子类重写的方法,如果子类继承了父类的方法(未重写),那么子类创建的对象也可以调用这个方法,只不过方法产生的行为和父类的相同而已。代码示例如下

[html] view
plaincopy





public class ExtendsDemo3 {

/**子类继承父类但未重写方法,而是直接调用

* @黑马ZWF

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

Circle yuan = new Circle();

float length = yuan.f(5.0f); //调用子类重写的方法f

float sum = yuan.g(232.645f, 418.567f); //调用从父类继承的方法E

System.out.println(length); //输出结果是31.415901

System.out.println(sum); //输出结果是651.212

}

}

class Area {

float f(float r) {

return 3.14159f * r * r;

}

float g(float x,float y) {

return x+y;

}

}

class Circle extends Area {

float f(float r) {

return 3.14159f * 2.0f * r;

}

}

二.接口

1.接口的概念

Java不支持多继承性,即一个类只能有一个父类。单继承性使得Java简单,易于管理程序。为了克服单继承的缺点,Java使用了接口,一个类可以实现多个接口。

使用关键字interface来定义一个接口。接口的定义和类的定义很相似,分为接口的声明和接口体。

2.接口的声明和使用

1)接口声明

前面曾使用class关键字来声明类,接U通过使用关键字interface来声明。格式:

interface 接口的名字

2)接口体

接口体中包含常量定义和方法定义两部分。接口体中只进行方法的声明,不许提供方法的实现,所以,方法的定义没有方法体,且用分号";"结尾。如:

[html] view
plaincopy





interface Printable { //该接口包含一个变量和一个方法

int max = 100;

void sum();

}

3)接口的使用

一个类通过使用关键字implements声明自己使用一个或多个接口。如果使用多个接口,用逗号隔开接口名。如:

类A使用接口Printable和接口Addable

class A implements Printable,Addable

类Dog使用接口Eatable和接口Sleepable

class Dog extends Animal implements Eatable,Sleepable

如果一个类使用了某个接口,那么这个类必须实现该接口的所有方法,即为这些方法提供方法体。需要注意的是:在类中实现接口的方法时,方法的名字、返同类型、参数个数及 类型必须与接口中的完全一致。特别要注意的是:接口中的方法默认是public abstract方法,所以类在实现接口方法时必须给出方法体,并且一定要用public来修饰,而且接口中的常量默认是public static常量。

由于接口体中只有常量定义和public的abstract方法定义,程序在编写接口时,允许省略常量前面的public. final和static修饰,也允许省略方法前面的public和abstract修饰。另外,如果接口方法的返回类型不足void型,那么在类中实现该接口方法时,方法体至少要有一个retum语句;如果是void型,类体除了两个大括号外,也可以没有任何语句。

Java提供的接口都在相应的包中,通过引入包可以使用Java提供的接口。也可以自己定义接口,一个Java源文件就是由类和接口组成的。只进行方法的声明,不许提供方法的实现,所以,方法的定义没有方法体,且用分号";"结尾。代码示例如下:

[html] view
plaincopy





public class InterfaceDemo2 {

/**一个接口的使用

* @黑马ZWF

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

A a = new A(); //创建一个对象

System.out.println(a.sum(12, 23)); //调用类A中的sum方法

}

}

interface qiuhe {

int sum(int x, int y); //写一个方法名 但不要将其实例化

}

class A implements qiuhe {

public int sum(int x, int y){ //注意不能省略public

return x + y;

}

}

4)理解接口

接口的语法规则很容易记住,但真正理解接口更重要。在上例如果去掉接口,该程序的运行没有任何问题。那为什么要用接口呢?

假如轿车、货车、拖拉机、摩托车、客车都是机动车的子类,其中机动车是一个抽象类。如果机动车中有两个抽象方法:“收取费用”、“调节温度”,那么所有的子类都要实现这两个方法,即给出方法体,产生各自的收费或控制温度的行为。这显然不符合人们的思维方法,因为拖拉机可能不需要有“收取费用”或“调节温度”的功能,而其他的一些类,比 如飞机、轮船等需要有“收取费用”或“调节温度”的功能。接口可以增加很多类都需要实现的功能,不同的类可以使用相同的接口,同一个类也可以实现多个接口。接口只关心功能,并不关心功能的具体实现,比如“客车类”实现一个接口,该接口中有一个“收取费用”的方法,那么这个“客车类”必须具体给出怎样收取费用的操作,即给出方法的方法体,不同车的类都可以实现“收取费用”,但“收取费用”的手段可能不相同。接口的思想在于它可以增加很多类都需要实现的功能,使用相同的接口类不一定有继承关系,就像各式各样的商品,它们珂能隶属不同的公司,工商部门要求都必须具有显示商标的功能(实现同一接口),但商标的具体制作由各个公司自己去实现。

再比如,你是一个项目主管,你需要管理许多部门,这些部门要开发一些软件所需要的类,你可能要求某个类实现一个接口,也就是说你对一些类是否具有这个功能非常关心,但不关心功能的具体体现。比如,这个功能是speakLove,但你不关心是用汉语实现功能speakLove还是用英语实speakLoveo在某些时候,你也许打一个电话就可以了,告诉远方的一个开发部门实现你所规定的接口,并建议他们用汉语来实现speakLoveo如果没有这个接口,你可能要花很多的口舌来让开发部门找到那个表达爱的方法,也许他们给表达爱的那个方法起的名字是完全不同的名字。

代码示例

[html] view
plaincopy





public class InterfaceDemo3 {

/**深入理解为什么需要使用接口

* @黑马ZWF

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

公共汽车 一路 = new 公共汽车(); //创建对象

出租车 天宇 = new 出租车(); //创建对象

电影院 奥斯卡 = new 电影院(); //创建对象

一路.收取费用();

天宇.收取费用();

奥斯卡.收取费用();

天宇.controlTemperature();

奥斯卡.controlTemperature();

}

}

interface 收费 { //定义收费接口

public void 收取费用();//收费接口中定义收取费用方法

}

interface 调节温度 { //定义调节温度接口

public void controlTemperature(); //定义调节温度方法

}

class 公共汽车 implements 收费 { //定义公共汽车类使用收费接口

public void 收取费用() { //重写收取费用方法,并给出实例

System.out.println("公共汽车:一元一张,不计算公里数");

}

}

class 出租车 implements 收费,调节温度 { //定义出租车类使用收费和调节温度接口

public void 收取费用() { //重写收取费用方法,并给出实例

System.out.println("出租车:1. 60元每公里,起价3公里");

}

public void controlTemperature() { //重写调节温度方法,并给出实例

System.out.println("安装了海尔空调");

}

}

class 电影院 implements 收费,调节温度 {

public void 收取费用() { //重写收取费用方法,并给出实例

System.out .println("电影院:门票,十元一张");

}

public void controlTemperature() { //重写调节温度方法,并给出实例

System.out.println("安装了美的空调");

}

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