文章目录
面向对象的三大特征: 封装,继承,多态
java面向对象的特征: 封装,继承,多态, 抽象,接口
1 多态
1.1 什么是多态,为什么要使用多态。
思考一个场景
需求1:动物园让我们实现一个功能: 创建一个狗类 ,狗有eat()函数,再创建一个饲养员类,饲养员有一个feed()函数,让饲养员喂养狗。思考:狗为什么非要人喂,狗不能自己吃吗?以后我们的代码,都是从一个类去调用另一个类,形成一个调用链。
需求2:此时动物园引进新品种 猫,此时需要创建一个猫类。并添加eat函数,让人类也能喂养猫。
需求3:此时动物园又引进了一种新动物,叫做pig猪 此时pig也有eat 并且 人类也需要喂养pig,请完成功能。
Animal
public class Animal {
// 吃的方法
public void eat(){
System.out.println("吃东西");
}
}
Cat
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
Dog
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗不想吃");
}
}
Feed 饲养员
public class Feeder {
public void Feed(Dog dog){
System.out.println("饲养员在喂狗");
dog.eat();
// 狗在吃东西
}
/**
* 喂猫
**/
public void Feed(Cat cat){
System.out.println("饲养员在喂猫");
cat.eat();
}
}
Test
public class Test {
public static void main(String[] args) {
// 饲养员 喂 dog
Feeder feeder = new Feeder();
Dog dog = new Dog();
feeder.Feed(dog);
Cat cat = new Cat();
feeder.Feed(cat);
// 喂猪
Pig pig = new Pig();
feeder.Feed(pig);
YingWu yingWu = new YingWu();
feeder.Feed(yingWu);
}
}
思考:动物园如果一直引进新的动物,饲养员一直喂养新的动物。此时跟我们面向对象的思想不符合。代码要一直修改,非常麻烦。怎么解决?使用多态!Feeder中的Feed方法修改之后:
public class Feed {
public void Feed(Animal animal){
System.out.println("喂");
animal.eat();
}
}
对应的Test
public static void main(String[] args){
Feeder feeder = new Feeder();
Animal cat = new Cat();
Animal dog = new Dog();
feeder.Feed(cat);
feeder.Feed(dog);
这样看来就简便了很多,代码量大的时候就很明显了。
1.2 什么是多态
**多态(Polymorphism)**按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自“Delphi4 编程技术内幕”)。简单的说,就是一句话:允许将子类类型赋值给父类类型。多态的前提是继承和方法重写。多态:父类对象表现多种子类的形态的能⼒的特征,⼀句话多态就是⽗类引⽤⼦类对象。 向同⼀个⽗类的不同⼦类发送同⼀条消息,⾏为不同。
父类指向子类的内存地址
向上转型
1.2.1 向上转型
向上转型:⽗类引⽤⼦类对象(⾃动成⽴,缺点是失去调⽤⼦类独有⽅法的能⼒)
向上转型后该对象只能当成父类对象来用,原来子类中定义的属性和方法就被屏蔽掉不能被调用了。比如狗里有一个【看门】的方法,如果向上转型后作为【动物】类就不能调用dog类独有的【看门】的方法。总结: 向上转型 从小的转向大的 缺点:不能调用子类里面的特有的方法
1.2.2 向下转型
向下转型:⼦类引⽤⽗类对象(强制转换,慎重)
此时可以调用子类对象中的方法和属性。
注意事项:ClassCastException
以上为继承多态 占据5% 继承多态。
接口多态95%。
向下转型: 大的转化为小的 缺点:强制类型转换 ClassCastException类型转换异常
2 抽象类
2.1为什么要用抽象
抽象类的抽象方法一定不能有实现(也就是不能有大括号),子类必须要override覆写抽象方法,从而让继承类的行为有一定规范;抽象类的方法不一定都是抽象方法,但抽象方法所在的类必须是抽象类;抽象类不能实例化,抽象类的继承类被实例化后可以直接调用抽象类的方法(抽象方法除外,抽象方法被继承类 override),不希望实例化而直接调用方法就可以用抽象类;
2.2 抽象方法和抽象类的格式
抽象类的存在不是为了创建对象,是为了让子类继承用的。抽象类:使用abstract关键字修饰的类。
[权限修饰符] abstract class 类名{}
抽象方法: 使用abstract关键字修饰的方法 注意:抽象方法没有方法体,也没有{}
[权限修饰符] abstract 返回值 方法名();//没有大括号
2.3 抽象类和抽象方法使用
封装了⼀个类,但是这个类不能实例化—定义成抽象类。好处是让所有的⼦类必须实现⽗类的抽象⽅法。 1)使⽤abstract修饰的类是抽象类
2)抽象类有构造,但是不能new
3)使⽤abstract修饰⽅法是抽象⽅法,抽象⽅法没有⽅法体(即没有{})
4)抽象类可以没有抽象⽅法
5)有抽象⽅法的类必须是抽象类
6)抽象类归根结底还是⼀个类,只不过作为⽗类为⼦类服务。所以可以有普通的属性和普通⽅法。 7)抽象类的⼦类:如果抽象类的子类不想实现父类的抽象方法,就需要把这个子类也变成抽象的
3 接口
3.1接口
接口:公共的规范,大家都要遵从这个规范使用。定制规则,展现多态。
接口其实就是一个特殊的抽象类; Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
两种含义:
一,Java接口,Java语言中存在的结构,有特定的语法和结构;
二,一个类所具有的方法的特征集合,是一种逻辑上的抽象。前者叫做“Java接口”,后者叫做“接口”。我们入门级别的认知可以这样理解: 接口就是一个特殊的抽象类。 从功能方面考虑 也就是说接口和抽象类相比 又有一些特殊的地方。
3.2 接口的定义
接口定义的格式
[权限修饰符] interface 接口名{}
接口的使用步骤
接口中的方法不能直接使用,必须有一个实现类来实现接口
[权限修饰符] class 类名 implements 接口1,接口2,接口3。。。{}public class Mouse implements USB{}
2.接口的实现类必须(覆盖重写)实现 接口中所有的抽象方法
3.创建实现类的对象,进行方法的调用。
注意:如果实现类没有覆盖重写接口中的方法,那么这个实现类自己就必须是抽象类。
接口中可以包含的内容常量 (不可变的)接口中的常量使用public static final 三个关键字修饰。
//定义常量的格式 public static final int AGE = 10;
直接使用 接口名.常量名接口可以多实现。一个类可以实现多个接口。
抽象方法注意事项:
接口中的抽象方法必须是两个固定的关键字修饰 public abstract
这两个关键字可以省略不写。
默认方法(jdk1.8以后的新增内容)
为什么要有默认方法? default 增强接口的通用能力。
注意事项
类与类之间是单继承的
类与接口是多实现的:一个类可以实现多个接口(这个要将所有实现的接口中的抽象方法都实现),方便后期维护(修改,扩展)
接口与接口之间是多继承的:一个接口A如果继承了接口B和接口C,那么A接口可以同时拥有B和C接口的所有功能,并且还可以拥有属于自己的方法。
接口没有构造方法。 接口多态:一个USB接口可以表现出鼠标形态,键盘的形态,U盘的形态。。。。。。
面试题:接口和抽象类的区别?
1.构造方法抽象类里面有构造方法 但是不能被new出来接口里面没有构造方法
2.继承抽象里面 java单继承 一个类只能继承一个抽象父类接口可以继承多个接口,一个类可以实现多个接口
3.抽象方法抽象类里面可以没有抽象方法,有抽象方法的类必须是抽象类接口里面的方法是必须是抽象方法,只有方法名没有方法体,如果不是抽象方法就必须是default修饰的方法抽象类里面的抽象方法是用public abstarct来修饰的 接口中的方法public abstract可以省略
4变量
接口中的变量是用public static final修饰的