多态、抽象类、接口

一、多态

1、使用多态:可以定义一个"父类类型的引用",指向它的"子类的对象",这种形式就叫:多态

父类 fl = new 子类();

Animala1 = new Cat();

2、多态的前提和体现;

1.一定要存在"继承关系";

2.方法重写;

3、成员变量的访问特点:

1.成员变量:编译看左边(父类中一定要有,否则编译错误);运行看左边(如果子类覆盖父类的成员变量,

   打印的是父类的)

2.成员方法:编译看左边(父类中一定要有,否则编译错误);运行时看右边(如果子类重写父类的成员方

   法,调用的是子类的)

3.静态方法:编译看左边(父类中一定要有,否则编译错误);运行时看左边(如果子类重写父类中的静态方

   法,调用的是父类的)

  总而言之:当多态时,访问的成员(成员变量、成员方法)父类中必须要有,否则编译错误。

   运行时,只有"被覆盖的普通成员方法"访问的是"子类的",其它都是"父类"的。

4、利用"多态"的特性。一个方法的形参可以声明为某个"父类"类型。就表示:可以接收任何的它的子类对象的引用。

5、多态的弊端:

1.当多态时,不能访问子类特有成员;

classA{

intn = 10;

}

classB extends A{

intm = 20;

}

main(){

Aa = new B();

System.out.println(a.m);//编译错误。

}

2.可以通过转型,去访问子类特有成员;

6、多态中的类型转换:

1.向上转型(隐式的,自动的):"父类"类型的变量,存储"子类对象"的引用;

Animal a = new Cat();//向上转型;

2.向下转型(显示的,强制转换):如果我们确定一个"父类"类型的变量,存储了某个具体的"子类对象"的引用。

  我们可以将这个"父类类型"强制转换为它所存储的"子类类型";

Animal a = new Cat();//向上转换

Cat c = (Cat)a;//向下转换

Dog d = (Dog)a;//错误。

3.向下转型由于要使用"强制转换",这就有了隐藏的危险。如果类型不匹配,将在运行时异常:ClassCastException。

 Java为我们提供了一种方式,在强制转换前,可以先进行判断,如果为true,再进行转换。

  使用关键字:instanceof

  它是双目运算符:左操作数 instanceof 右操作数

左操作数:一般是一个"变量名";

右操作数:是某个"类名"

整体的意思:"左操作数"是否是"右操作数"的类型:是:返回true,否则:返回:false

 

Animala = new Cat();

if(ainstanceof Cat){

Cat c = (Cat)a;//转换是安全的;

}

if(ainstanceof Dog){

Dogd = (Dog)a;

}

7、孔子装爹案例:

class 孔爹{

intage = 75;

 

voidteach(){

System.out.println("孔爹讲Java");

}

}

class 孔子extends 孔爹{

intage = 30;

 

voidteach(){

System.out.println("孔子讲IOS");

}

 

voidplayGame(){

System.out.println("打英雄联盟");

}

}

 

主程序:

main(){

//当前孔爹已经被人请走讲课去了。只有孔子在家。这时又来人请孔爹去讲Java,孔爹没在家,孔子一看

//来人给的价钱也很高,于是乎:孔子打算替他爹出山。于是,进入带上胡子,穿上孔爹的袍子,跟人走了。

孔爹 kd = new 孔子();

System.out.println("我今年:" + kd.age);//我今年:75

 

kd.teach();//IOS

 

kd.playGame();//编译错误

 

//孔子回家,卸妆

孔子 kz = (孔子)kd;

 

//打游戏

kz.playGame();//OK的

}

 

代码实现:

class 孔爹{

intage = 75;

 

voidteach(){

System.out.println("孔爹讲Java");

}

}

class 孔子extends 孔爹{

intage = 30;

 

voidteach(){

System.out.println("孔子讲IOS");

}

 

voidplayGame(){

System.out.println("打英雄联盟");

}

}

classDemo

{

publicstatic void main(String[] args)

{

//当前孔爹已经被人请走讲课去了。只有孔子在家。这时又来人请孔爹去讲Java,孔爹没在家,孔子一看

//来人给的价钱也很高,于是乎:孔子打算替他爹出山。于是,进入带上胡子,穿上孔爹的袍子,跟人走了。

孔爹 kd = new 孔子();

System.out.println("我今年:" + kd.age);//我今年:75

 

kd.teach();//IOS

 

//        kd.playGame();//编译错误

 

//孔子回家,卸妆

孔子 kz = (孔子)kd;

 

//打游戏

kz.playGame();//OK的

}

}

 

二、抽象类

1.一般不会实例化"父类"的对象;因为"父类"没有对应现实世界中的实体。我们经常使用子类。

2.父类会定义某些方法,而这个方法会被每个子类重写。

classPerson{

voidshow(){

System.out.println("我是传智播客的一员");

}

}

classStudent extends Person

{

//重写

voidshow(){

System.out.println("我是传智播客的一名学生,我骄傲!!");

}

classTeacher extends Person{

//重写

voidshow(){

System.out.println(我是传智播客的一名教师,我骄傲!!");

}

3.基于上述,以及一些其它原因:

1.某些父类既然不会去实例化,那么就干脆将这个类定义为:不可实例化的;这种类就叫:抽象类

2.父类中的某些方法,都会被子类重写,那么干脆:父类只提供"方法签名",不提供"具体实现"。

  这种方法就叫:抽象方法;

4.定义抽象类,使用关键字:abstract

 

5.可以修饰:

1.类:abstract class类名{}

  说明:此类将不能被实例化;就是用来做父类的,让子类去继承的;

2.成员方法:abstarctvoid show();

  说明:此方法是个"抽象方法",用来被子类"重写的"

6.说明:

1.一个"抽象类"中可以没有抽象方法;

2.如果一个类中包含了"抽象方法",那么这个类必须是"抽象类";

3.如果一个"子类"继承"抽象类",仍然使用关键字:extends。而且仍然是"单继承";

4.如果一个"子类"继承了"抽象类",那么必须重写全部的"抽象方法"。如果不重写,或不完全重写,

  那么这个"子类"也必须是个"抽象类"。

  从另一个角度:一个抽象类,可以继承自另一个抽象类;

7、抽象类:

1.抽象类中可以没有抽象方法;也可以什么都没有;

2.如果抽象类中包含了抽象方法,那么这个类必须要声明为抽象的;

3.抽象类中可以有什么:

1).成员变量;

2).构造方法,并且可以重载;为成员变量赋值;

3).普通,实现的成员方法:

4).抽象方法;

4.抽象类跟普通的父类的区别:

1).抽象类不能被实例化;

2).抽象类中可以包含抽象方法;

8、面试题

一.一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?

1.可以(一个抽象类内部,可以什么都不定义);

2.只是父类使用。而且这个父类不可以实例化;

 

二.abstract不能和哪些关键字共存:

1.private:因为一个抽象方法就是被子类重写的。要重写就必须不能为private的。

2.final:因为一个抽象方法就是被子类重写的。而final表示:最终方法,不能被重写。所以这两个关键字冲突;

       作用在"类"上也是一样:一个抽象类就是用来被继承的。而final类:表示最终类,不能被继承。所以也是冲突;

3.static:因为一个抽象方法没有方法体。所以不能定义为static的。因为无法被分配空间;

 

三、接口

1、如果一个抽象类中,没有成员变量,没有实现的方法,只包含了一些"抽象方法",这时,我们可以将

这个类定义为"接口":

1.定义接口,使用关键字:interface

2.接口:不能被实例化,用来被子类"实现"的;

3.子类实现接口,使用关键字:implements

4.接口中可以包含(JDK8以前):

1).成员变量:必须被声明为:publicstatic final。如果不写这几个修饰符,系统会自动添加.

2).抽象方法:必须被声明为:publicabstract。如果不写这几个修饰符,系统会自动添加。

5.接口的作用:

1).Java是"单继承"的,不能同时继承多个类。

   Java的一个类实现接口时,可以同时实现多个接口;

  所以,在Java中,通过"实现接口"达到"功能扩展的目的";

6、重写接口中的抽象方法时,必须要使用:public访问修饰符;

2、接口的使用:

1、接口的作用就是用来扩展功能

2、一个子类,可以同时实现一个或者多个接口

3、一个子类可同时继承一个类,并实现一个或者多个接口,但是一定要先继承,后

     实现接口

4、一个子类,如果实现一个接口,那么必须从写接口中的抽象方法,否则这个子类

     也得是一个抽象的

5、一个接口可以继承自另一个或者多个接口,也就意味着使用关键字extends,并且

     可以多继承

例:interface A{

}

         inteface  B{

}

         interface C extendsA,B{

}

3、类和类,类和接口,接口和接口之间的关系:

1.类和类:继承:使用关键字:extends;单继承;

2.类和接口:实现;使用关键字:implements;可以同时实现多个接口

3.接口和接口:继承:使用关键字:extends;可以多继承;

 

上述中说的类都包含"抽象类"

 

四、抽象类和接口的区别

1、成员:

抽象类:成员变量、常量、构造方法、实现的方法、抽象方法

接口:常量、抽象方法

2、关系

抽象类:子类是继承,使用关键字extends

接口:子类是实现,使用关键字:implements

 

类和类:是继承 使用extends

类和接口:是实现,使用implements

接口和接口:是继承,使用extends

3、设计理念

抽象类:被设计为“is a”的关系

接口:接口:被设计为"like a"的关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值