多态
多态是继封装、继承之后,面向对象的第三大特性。
生活中,比如跑的动作,小猫、小狗和大象,跑起来是不一样的。再比如飞的动作,昆虫、鸟类和飞机,飞起来也是不一样的。可见,同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态
定义
- 多态: 是指同一行为,对于不同的对象具有多个不同表现形式。
- 程序中多态: 是指同一方法,对于不同的对象具有不同的实现
前提条件【重点】
- 继承或者实现【二选一】
- 父类引用指向子类对象\接口引用指向实现类对象【格式体现】
- 方法的重写【意义体现:不重写,无意义】
多态的体现:父类的引用指向它的子类的对象:
父类类型 变量名 = new 子类对象;
变量名.方法名();
父类类型:指子类对象继承的父类类型,或者实现的父接口类型。
多态的好处和弊端
好处
- 提高了代码的扩展性
弊端
- 多态的情况下,只能调用父类的共性内容,不能调用子类的特有内容。
- 无法访问子类独有的方法或者成员变量,因为多态成员访问的特点是,编译看父类
public class Animal {
public void eat(){
System.out.println("吃东西");
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
public void jidu(){
System.out.println("狗缉毒");
}
}
public class Test1 {
public static void main(String[] args) {
Animal cat = new Cat();
cat.eat();
Animal dog = new Dog();
dog.eat();
// dog.zjidu();
}
}
好处
public class Test2 {
public static void main(String[] args) {
Cat cat = new Cat();
show(cat);
Dog dog = new Dog();
show(dog);
}
// 假设有一个方法 需要传入cat或者dog作为参数我们需要这么写(两个方法)
public static void show(Dog dog){
dog.eat();
}
public static void show(Cat cat){
cat.eat();
"".equals("a");
}
}
public class Test3 {
public static void main(String[] args) {
Animal cat = new Cat();
show(cat);
Animal dog = new Dog();
show(dog);
}
// 假设有一个方法 需要传入cat或者dog作为参数我们需要这么写(两个方法)
public static void show(Animal animal){
animal.eat();
}
}
多态的应用场景
- 形参多态----> 常用
public class Test3 {
public static void main(String[] args) {
Animal cat = new Cat();
show(cat);
Animal dog = new Dog();
show(dog);
}
// 假设有一个方法 需要传入cat或者dog作为参数我们需要这么写(两个方法)
public static void show(Animal animal){
animal.eat();
}
}
- 返回值多态—> 常用
public class Test4 {
public static void main(String[] args) {
// 返回值多态:如果返回值类型为父类类型,那么就可以返回该父类类型的对象或者其所有子类对象
Animal animal = m1(2);
animal.eat();
}
public static Animal m1(int n){
if (n==1)
return new Animal();
else if (n==2)
return new Cat();
else
return new Dog();
}
}
引用类型转换
向上转型
- 子类类型向父类类型向上转换的过程,这个过程是默认的。
Aniaml anl = new Cat();
向下转型
- 父类类型向子类类型向下转换的过程,这个过程是强制的。
Aniaml anl = new Cat();
Cat c = (Cat)anl;//向下转型
public class Test5 {
public static void main(String[] args) {
Animal dog = new Dog(); // 向上转型
Dog dog1 = (Dog)dog;
// Dog dog1 = (String)dog; 编译报错,因为Animal和String不是父子关系
dog1.jidu();
}
}
instanceof关键字
- 向下强转有风险,最好在转换前做一个验证 :
变量名 instanceof 数据类型
如果变量属于该数据类型,返回true。
如果变量不属于该数据类型,返回false。
案例
public interface USB {
void open();
void close();
}
public class Mouse implements USB{
@Override
public void open() {
System.out.println("鼠标开启, 红灯闪一闪");
}
@Override
public void close() {
System.out.println("鼠标关闭, 红灯灭一灭");
}
public void click(){
System.out.println("鼠标单击");
}
}
public class KeyBoard implements USB{
@Override
public void open() {
System.out.println("键盘开启, 绿灯闪一闪");
}
@Override
public void close() {
System.out.println("键盘关闭, 绿灯灭一灭");
}
public void type(){
System.out.println("键盘打字");
}
}
public class MacBook {
public void run() {
System.out.println("笔记本开机.....");
}
public void useUSB(USB usb){
usb.open();
if (usb instanceof Mouse){
Mouse mouse = (Mouse)usb;
mouse.click();
}
if (usb instanceof KeyBoard){
KeyBoard keyBoard = (KeyBoard)usb;
keyBoard.type();
}
usb.close();
}
public void shutDown() {
System.out.println("笔记本关机.....");
}
}
public class Test {
public static void main(String[] args) {
MacBook macBook = new MacBook();
macBook.run();
USB mouse = new Mouse();
macBook.useUSB(mouse);
USB keyBoard = new KeyBoard();
macBook.useUSB(keyBoard);
macBook.shutDown();
}
}