[2017.10.21-22]多态&抽象类&接口
来源:互联网 发布:mac终端重设密码 编辑:程序博客网 时间:2024/06/05 14:31
多态
1.多态:一个事物在不同时刻体现出来的不同状态.
2.对于多态的三个前提条件(缺一不可) :
1)必须有继承关系(如果没有继承关系,谈不上多态!)
2)必须有方法重写
3)有父类引用指向子类对象:向上转型
3.多态的成员访问特点:
1)成员变量:
编译看左边,运行看左边
2)成员方法(非静态的成员方法):
编译看左,运行看右;由于存在方法重写,所以就运行最终的就是子类的成员方法
3)静态成员方法:(静态方法算不上方法重写,静态直接跟类有关系!)
编译看左,运行看左
4)构造方法:还是对象进行初始化,由于是一种继承关系,还是分层初始化
4.演示:
//父类class Fu{ public int num = 10 ; //父类的成员方法 public void show(){ System.out.println("show Fu..."); } //静态方法 public static void function(){ System.out.println("function Fu...."); }}//子类class Zi extends Fu{ int num = 20 ; public void show(){ System.out.println("show Zi..."); } public static void function(){ System.out.println("function Zi...."); }}//测试类public class DuoTaiDemo { public static void main(String[] args) { //创建父类的对象:多态的形式// 有父类引用指向子类对象:向上转型 Fu f = new Zi() ; //访问成变量 System.out.println(f.num); //调用成员方法:show() f.show() ; //静态方法 f.function() ; }}
5.多态的好处(特点):
1)提高代码的维护性(由继承保证)
2)提高代码的扩展性(由多态保证)
(java的开发原则:低耦合,高内聚)
6.演示:
//父类class Animal{ public void eat(){ System.out.println("eat"); } public void sleep(){ System.out.println("sleep..."); }}//猫类class Cat extends Animal{ public void eat(){ System.out.println("猫吃鱼..."); } public void sleep(){ System.out.println("猫趴着睡..."); }}//狗类class Dog extends Animal{ public void eat(){ System.out.println("狗吃骨头..."); } public void sleep(){ System.out.println("狗躺着睡...."); }}//猪类class Pig extends Animal{ public void eat(){ System.out.println("猪吃白菜..."); } public void sleep(){ System.out.println("猪卧着睡...."); }}//写一个动物的工具类class AnimalTool{ //将类中无参构造私有化:目的是为了不让外界创建对象! /*private AnimalTool(){ }*/ //形式参数是一个父类 public void useAnimal(Animal a){ a.eat() ; a.sleep() ; }}//测试类public class DuoTaiDemo2 { public static void main(String[] args) { //我喜欢猫,养一只猫 Cat c1 = new Cat() ; c1.eat() ; //还喜欢猫,又养了一只 Cat c2 = new Cat() ; c2.eat() ; //... Cat c3 = new Cat() ; c3.eat() ; System.out.println("---------------------"); //优化改进:将猫的吃和睡的方法封装成独立的功能 /*useCat(c1) ; useCat(c2) ; useCat(c3) ;*/ Dog d1 = new Dog() ; Dog d2 = new Dog() ; Dog d3 = new Dog() ; //调用狗的功能 /*useDog(d1) ; useDog(d2) ; useDog(d3) ;*/ Pig p1 = new Pig() ; Pig p2 = new Pig() ; Pig p3 = new Pig() ; System.out.println("------------------------"); //最终版代码 //先创建AnimalTool对象 AnimalTool at = new AnimalTool() ; at.useAnimal(c1) ;//形式参数:Animal a = new Cat(); at.useAnimal(c2) ; at.useAnimal(c3) ; System.out.println("-------------------------"); at.useAnimal(d1) ; at.useAnimal(d2) ; at.useAnimal(d3) ; System.out.println("-------------------------"); at.useAnimal(p1) ; at.useAnimal(p2) ; at.useAnimal(p3) ; } //写一个功能 /*public static void useCat(Cat c){ c.eat() ; c.sleep() ; } public static void useDog(Dog d){ d.eat() ; d.sleep() ; }*/}
7.多态的弊端:
不能访问子类的特有功能
8.演示:
class Animal2{ public void show(){ System.out.println("show Animal2..."); }}//子类class Cat2 extends Animal2{ public void show(){ System.out.println("show Cat2...."); } //特有功能 public void playGame(){ System.out.println("猫玩毛线..."); }}//测试类public class DuoTaiDemo3 { public static void main(String[] args) { //多态的形式:父类引用指向子类对象 Animal2 a = new Cat2() ; a.show() ;// a.playGame() ; }}
9.多态的弊端:
不能访问子类的特有功能.
解决方案:
1)创建子类的具体对象,来访问自己的特有功能;虽然可以解决多态的弊端,但是从内存角度考虑,需要创建子类对象,那么必须在堆内存开辟空间, 耗费内存,浪费空间!
2)既然多态的第三个前提条件:父类引用指向子类对象,那么可以向下转型:将父类的引用强制转换为子类的引用(前提必须有父类的引用存在)
3)向下转型必须依赖于向上转型!
10.演示:
class Animal3{ public void show(){ System.out.println("show Animal2..."); }}//子类class Cat3 extends Animal3{ public void show(){ System.out.println("show Cat2...."); } //特有功能 public void playGame(){ System.out.println("猫玩毛线..."); }}public class DuoTaiDemo4 { public static void main(String[] args) { //父类引用指向子类对象 Animal3 a = new Cat3() ; //向上转型 a.show() ; //不能访问子类特有功能// a.playGame(); //创建子类具体对象 /* Cat3 c = new Cat3() ; c.playGame() ;*/ //父类的引用强制转换为子类的引用:向下转型 Cat3 c = (Cat3) a ; c.playGame() ; }}
11.一般情况下,向下转型使用不当会造成异常.
12.演示:
class Animal4{ public void eat(){}}class Cat4 extends Animal4{ public void eat(){} public void playGame(){}}class Dog4 extends Animal4{ public void eat(){} public void lookDoor(){}}//测试类:public class DuoTaiDemo5 { public static void main(String[] args) { //内存是狗 Animal4 a = new Dog4() ; //向下转型:还原成狗 Dog4 d = (Dog4)a ; //内存是猫 a = new Cat4() ; //还原成猫 Cat4 c = (Cat4) a ; //编译通过了 Dog4 dd = (Dog4)a ; //不能将内存猫转换为狗 }}
13.有继承关系 分层初始化:
父类先初始化,然后子类初始化
14.多态的访问特点:
成员方法(非静态的):
编译看左,运行看右(方法重写)
15.练习:
①
class A { public void show() { show2(); } public void show2() { System.out.println("我"); }}class B extends A { /** * public void show(){ * show2() ; * } * */ public void show2() { System.out.println("爱");//爱 }}class C extends B { public void show() { super.show(); } public void show2() { System.out.println("你");//你 }}public class DuoTaiTest { public static void main(String[] args) { A a = new B(); a.show(); B b = new C(); b.show(); // 2)爱你 }}
②
//猫狗案例练习多态版/** * 猫 * eat() * sleep() * 狗 * eat() * sleep() * * 动物类:Animal * * */class Animal5{ public void eat(){ System.out.println("动物饿了就需要吃饭..."); } public void sleep(){ System.out.println("动物困了,需要休息..."); }}//子类class Cat5 extends Animal5{ @Override public void eat(){ System.out.println("猫吃鱼..."); } public void sleep(){ System.out.println("猫趴着睡觉..."); }}class Dog5 extends Animal5{ @Override public void eat(){ System.out.println("狗吃骨头..."); } public void sleep(){ System.out.println("狗躺着睡觉..."); }}//测试类public class DuoTaiTest2 { public static void main(String[] args) { //创建对象 //多态版(实际开发中:多态使用最广泛:接口多态是经常使用的!) Animal5 a = new Cat5() ; a.eat() ; a.sleep() ; a = new Dog5() ; a.eat() ; a.sleep(); }}
③
//不同地方饮食文化不同的案例class Person{ public void eat(){ System.out.println("eat"); }}//南方人class SourthPerson extends Person{ public void eat(){ System.out.println("南方人喜欢吃米饭..."); } //特有功能 public void business(){ System.out.println("南方人爱经商...."); }}//北方人class NorthPerson extends Person{ public void eat(){ System.out.println("北方人爱吃馒头..."); } //特有功能 public void yanJiu(){ System.out.println("北方人爱研究...."); }}//测试类public class DuoTaiTest3 { public static void main(String[] args) { //多态版测试 Person p = new SourthPerson() ; p.eat() ;// p.business() ; SourthPerson sp = (SourthPerson) p ; sp.eat() ; sp.business() ; System.out.println("------------------"); //测试北方人 Person p2 = new NorthPerson() ; p2.eat() ; NorthPerson np = (NorthPerson) p2 ; np.yanJiu() ; }}
抽象类
1.抽象类的概念:
每一个动物的吃和睡的功能不一样,不应该把动物类定义为一个具体类,而是给出一个声明(abstract).
当一个类中如果有抽象功能(抽象方法)的时候,那么这个类一定要定义为抽象类!
2.一个抽象类中可以有非抽象方法吗?
一个抽象类中可以抽象,也可以有非抽象的
3.抽象类不能实例化:抽象类不能创建对象
如何进行实例化:
通过抽象类多态形式.父类的引用指向子类对象,通过子类进行初始化
4.抽象类的子类的特点:
1)抽象类的子类是抽象类,那么没有意义!
(最终使用的就是通过子类进行对象初始化的,如果子类都被抽象修饰了,那么也不能创建对象,所以没意义)
5.抽象类多态:
强制子类必须重写当前抽象的父类中所有的抽象方法
还可以提高代码的维护性
6.演示:
abstract class Animal{ //抽象方法:没有方法体的一个方法 public abstract void eat() ; public abstract void sleep() ; //具体方法 /*public void eat(){ System.out.println("eat"); }*/ public void show(){ System.out.println("show Animal...."); }}//抽象的子类//abstract class Cat extends Animal{// //}//子类是具体类class Cat extends Animal{ @Override public void eat() { System.out.println("猫吃鱼"); } @Override public void sleep() { System.out.println("猫趴着睡觉.."); }}//测试类public class AbstractDemo { public static void main(String[] args) { //当前Animal已经被abstract修饰了// Animal a = new Animal();//Cannot instantiate the type Animal:抽象类不能实例化:instaceof //多态:父类引用指向子类对象 Animal a = new Cat() ; //Animal是抽象类,---->抽象类多态形式 a.eat() ; a.sleep() ; }}
7.抽象类的成员特点
1)成员变量:
可以是变量也可以是自定义常量
2)构造方法:
抽象类可以有构造方法:包括有参构造和无参构造
作用:通过抽象类多态的形式:让子类进行数据的初始化
3)成员方法:
可以有抽象方法,也可以有非抽象方法
抽象类的成员方法特性:
a.抽象方法:强制子类必须要做到一件事情:方法重写(覆盖)
b.非抽象方法:由继承保证可以去提高代码的复用性
8.演示
abstract class Fu{ private String name ; private int age ; //成员变量 public int num = 100 ; public final int num2 = 200 ; //被final修饰:自定义常量 //无参构造 public Fu(){ } //有参构造 public Fu(String name,int age){ this.name = name ; this.age = age ; } //抽象方法 public abstract void show(); //非抽象方法 public void function(){ System.out.println("function Fu..."); }}//子类class Zi extends Fu{ @Override public void show(){ System.out.println("show Zi...."); }}//测试类public class AbstractDemo2 { public static void main(String[] args) { //抽象类多态: //抽象类的类名 对象名= new 子类名() ; Fu f = new Zi() ; f.show() ; f.function() ; }}
9.一个类中如果没有抽象方法,那么这个类可以定义为一个抽象类
10.abstract不能和哪些关键字共同使用?
private 和abstract\final和abstract\static和abstract不能共同使用
实际开发中:public 公共访问权限
10.演示:
abstract class Fu2{ //无参构造// private Fu2(){// // }// 抽象方法 public abstract void show() ; //非法修饰// private abstract void function() ; //非法修饰:编译不通过// public final abstract void function() ; //非法修饰// public static abstract void function() ;}class Zi2 extends Fu2{ public void show(){ System.out.println("show Zi2...."); }}//测试类public class AbstractDemo3 { public static void main(String[] args) { //抽象类多态...创建对象 }}
接口
1.接口的概念:
接口体现的是一种扩展功能
比如:猫可以跳高(并不是所有的猫都具有跳高功能)
2.如何表示接口:
interface:接口 interface 接口名{
}
3.接口里面的方法只能是抽象方法
接口中不能有构造方法
4.接口的特点:
不能实例化(不能直接创建对象)
5.接口实例化:
通过子实现类对数据进行初始化
接口的子实现类:
1)接口的子实现类是抽象类,没有意义,子类都不能创建对象了;实际开发中用的就是子类的对象进行初始化!
2)接口的子实现类是非抽象类
6.接口的子实现类和接口的关系:implements
7.格式:
class 子实现类名 implments(实现) 接口名{
8.演示:
//定义跳高的接口interface Jump{ //非抽象方法:抽象类中不能有抽象方法// public void jump(){// System.out.println("猫可以跳高了...");// } public abstract void jump() ; //构造方法:不能有// public Jump(){// // }}//子实现类是抽象类类//abstract class Cat implements Jump{//子实现类是非抽象类class Cat implements Jump{ @Override public void jump() { System.out.println("猫可以跳高了..."); }}//测试类public class InterfaceDemo { public static void main(String[] args) { //创建接口对象// Jump j = new Jump() ;//接口不能实例化 //接口多态:接口的引用指向子实现类对象 Jump j = new Cat() ; j.jump(); }}
9.接口成员的特点:
1)成员变量:
只能是常量:存下默认修饰符:public static final (永远建议自己给出默认修饰符)
2)构造方法:
接口是没有构造方法的
3)成员方法:
接口中的成员方法默认修饰符:public abstract(永远建议自己给出默认修饰符)
10.演示
//定义一个接口interface Inter{ public static final int num = 100 ; public static final int num2 = 200 ; //抽象方法// public void show();// void show() ; //全部给出默认修饰符 public abstract void show() ; //接口没有构造方法// public Inter(){// // } public abstract void function() ;}//定义接口的子实现类:见名知意:接口名+implclass InterImpl implements Inter{ @Override public void show() { System.out.println(num); System.out.println(num2); } @Override public void function() { System.out.println("function InterImpl..."); }}//测试类public class InterfaceDemo2 { public static void main(String[] args) { //创建接口对象:接口多态的形式 Inter i = new InterImpl() ;// i.num = 20 ;//当前num变量:被final修饰 System.out.println(Inter.num);//接口名.成员变量(当前变量被static修饰) System.out.println(Inter.num2); System.out.println("-------------"); i.show() ; i.function() ; }}
11.类与类的关系:
继承关系:extends,java中只支持单继承,不支持多继承,但是可以多层继承!
12.类与接口的关系
实现关系:implements,并且,一个类在继承另一个类的同时,可以实现多个接口
(class 子实现类名 enxtends Object implements 接口名1,接口名2…)
13.接口与接口的关系
继承关系:extends,可以支持单继承,也可以多继承!
14.演示:
interface Inter2{}interface Inter3{}//接口与接口的关系:extendsinterface Zi extends Inter2{}interface Son extends Inter2,Inter3{}//子实现类class InterImpl2 extends Object implements Inter2,Inter3{}public class InterfaceDemo3 {}
15.面试题:接口和抽象类的区别?
1)成员的区别:
①成员变量:
抽象类:成员变量可以是常量,也可以是变量
接口:成员变量只能是一常量:存在默认修饰符:public static final
②构造方法:
抽象类:可以有无参构造,有参构造方法
作用:通过子类进行数据初始化(通过子类创建对象)
接口:没有构造方法的
③成员方法:
抽象类:可以有抽象方法,也可以有非抽象方法
接口:只能是抽象方法:存在默认修饰符:public abstract
2)关系的区别:
①类与类的关系:
继承关系:extends,java中只支持单继承,不支持多继承,但是可以多层继承!
②类与接口的关系:
实现关系:implements,并且,一个类在继承另一个类的同时,可以实现多个接口
(class 子实现类名 enxtends Object implements 接口名1,接口名2…)
③接口与接口的关系
继承关系:extends,可以支持单继承,也可以多继承!
3)设计理念的区别:
抽象类:
体现的是一种”is a”的关系,存在继承关系!(抽象类多态)
接口:
体现的是一种”like a”的关系,由于接口的一种扩展功能.
16.练习:
/** * 猫狗案例,加入跳高的额外功能 * 分析:具体到抽象 * 猫: * 成员变量:姓名,年龄 * 构造方法:有参/无参 * 成员方法:setXXX()/getXXX() * eat(),sleep() * playGame() * 狗: * * 成员变量:姓名,年龄 * 构造方法:有参/无参 * 成员方法:setXXX()/getXXX() * eat(),sleep() * lookDoor() * * 抽取一个独立的类:动物类:Animal类:抽象类 eat();抽象功能 * * 猫继承自Animal * 狗继承自Animal * * 部分猫和狗具有跳高功能: * 接口: Jump * 跳高的抽象功能 * * 实现:抽象-->具体 * * * * * */public class InterfaceTest { public static void main(String[] args) { //实现接口的类是最具体的类,里面的功能最多:创建该类对象 //测试类跳高猫 JumpingCat jc = new JumpingCat() ; jc.setName("Tom") ; jc.setAge(5) ; String name = jc.getName() ; System.out.println(name);// System.out.println(jc.getName()+"---"+jc.getAge()); jc.eat() ; jc.sleep() ; jc.playGame() ; jc.jump() ; System.out.println("--------------------"); //通过有参构造进行数据初始化 jc = new JumpingCat("加菲猫", 5) ; System.out.println(jc.getName()+"---"+jc.getAge()); jc.eat() ; jc.sleep() ; jc.playGame() ; jc.jump() ; }}
//动物的抽象类public abstract class Animal { //成员变量 private String name ; private int age ; public Animal() { super(); } public Animal(String name, int age) { super(); this.name = name; this.age = age; } //setXXX/getXXX() public String getName() { return this.name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } //抽象功能 public abstract void eat() ; //非抽象 public void sleep(){ System.out.println("困了就需要休息..."); }}
public class Cat2 extends Animal { public Cat2() { super(); } public Cat2(String name, int age) { super(name, age); } @Override public void eat() { System.out.println("猫吃鱼..."); } public void playGame(){ System.out.println("猫玩游戏...."); }}
//跳高接口public interface Jumping { //抽象功能 public abstract void jump();}
//部分跳高猫首先应该是猫的一种,然后会跳高所以需要实现接口,重写里面的jump()方法public class JumpingCat extends Cat2 implements Jumping { public JumpingCat() { super(); } public JumpingCat(String name, int age) { super(name, age); } @Override public void jump() { System.out.println("猫可以跳高了..."); }}
- [2017.10.21-22]多态&抽象类&接口
- 多态,抽象类,接口
- 抽象类、接口、多态
- 多态、抽象类、接口
- 抽象类 接口 多态
- 多态、抽象类、接口
- 多态,抽象类,接口
- 抽象类 接口 多态
- 多态,抽象类,接口
- 抽象类 接口 多态
- 多态 抽象类 接口
- 多态,抽象类,接口
- 多态-抽象类-接口
- 多态/接口/抽象类
- 继承、多态、抽象类、接口
- 接口,抽象类,继承,多态
- 5 多态 抽象类 接口
- 继承,抽象类,接口,多态
- 安卓开发小记1
- [NOIP模拟][数学]Fibonacci
- Java 9 新特性快速预览
- Snackbar的简单使用
- IP数据报格式及如何判断报文类型
- [2017.10.21-22]多态&抽象类&接口
- 字符串
- jenkins编译android apk包
- [Android] i.MX6 Android源码中分离U-Boot和Linux-Kernel独立编译环境
- 减少HTTP请求之将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片(大型网站优化技术)
- 计算机色彩控制
- 高德地图机器学习岗位面试问题
- Bootstrap2 轮播 自动播放 该怎么设置
- iOS中的静态库与动态库,区别、制作和使用