JAVA中多态与接口
1.多态的概述
-
多态概述
-
指的是某一个事物,在不同时刻表现出来的不同状态。
-
多态常见表现方式:
Animal an=new Cat();
这样就可以将cat类型看做一种动物(Animal)
-
-
多态前提
-
要有继承关系。
-
要有方法重写。 其实没有也是可以的,但是如果没有这个就没有意义。
-
要有父类引用指向子类对象。
Animal an=new Cat();
-
-
多态中的成员访问特点
-
成员变量
- 编译看左边,运行看左边。
-
构造方法
- 创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化。(继承的特点)
-
成员方法
- 编译看左边,运行看右边
- 如果父类没有想要调用的子类特有方法,则无法调用
- 方法重写
-
静态方法
- 编译看左边,运行看左边。(静态不能重写,访问还是左边的)
-
案例演示
public class MyTest { public static void main(String[] args) { //多态的方式 Animal an = new Cat(); //多态要有方法重写 an.eat(); //编译看左边,运行看右边 int num = an.num; System.out.println(num); //编译看左边,运行也看左边。 //多态形式创建对象,还是先初始父类数据,再初始化自己 } } class Animal { String name; int age; int num = 6; public void eat() { System.out.println("吃饭"); } public void sleep() { System.out.println("睡觉"); } public static void show() { System.out.println("fu show"); } } class Cat extends Animal { int num = 100; @Override public void eat() { System.out.println("猫吃鱼"); } public void catchMouse() { System.out.println("老鼠"); } class Dog extends Animal { public void lookDoor() { System.out.println("狗看门"); } }
-
-
多态的好处
-
提高了代码的维护性(继承保证)
-
提高了代码的扩展性(由多态保证)
-
案例演示
public class MyTest { public static void main(String[] args) { Cat cat = new Cat(); MyUtils.testEat(cat); Dog dog = new Dog(); Dog dog1 = new Dog(); MyUtils.testEat(dog); }
public class MyUtils { private MyUtils() { } public static void testEat(Animal an) {//使用多态的方法 an.eat(); } }
public class Cat extends Animal { public void eat() { System.out.println("猫吃鱼"); } } public class Dog extends Animal { public void eat() { System.out.println("狗吃骨头"); } }
-
-
多态的弊端以及向下转型
-
不能使用子类特有的功能
-
向下转型
-
案例演示
public class MyTest { public static void main(String[] args) { //多态就是向上转型。 Cat cat = (Cat) an; //向下转型。 System.out.println(cat.num); cat.catchMouse(); System.out.println("===================================="); Animal an = new Cat(); an.eat(); //向下转型 Cat cat = (Cat) an; cat.catchMouse(); //类型转换异常。 an = new Dog(); Dog dog = (Dog) an; dog.lookDoor(); //猫狗不能互相转型 } }
-
-
多态中的题目分析
A:看下面程序是否有问题,如果没有,说出结果
class Fu {
public void show() {
System.out.println("fu show");
}
}
class Zi extends Fu {
public void show() {
System.out.println("zi show");
}
public void method() {
System.out.println("zi method");
}
}
class DuoTaiTest3 {
public static void main(String[] args){
Fu f = new Zi();
f.method(); //报错 ,父类没有此方法
f.show();
}
}
B:看下面程序是否有问题,如果没有,说出结果
class A {
public void show() {
show2();
}
public void show2() {
System.out.println("我");
}
}
class B extends A {
public void show2() {
System.out.println("爱");
}
}
class C extends B {
public void show() {
super.show();
}
public void show2() {
System.out.println("你");
}
}
public class DuoTaiTest4 {
public static void main(String[] args) {
A a = new B();
a.show(); //爱(先看a有没有show,有的话看有没有方法重写)
B b = new C();
b.show(); //你(先看a,b有没有show,有的话再看c有没有方法重写)
}
}
2.抽象类的概述
-
概述
- 动物本身并不是一个具体的事物,而是一个抽象的事物
- 只有真正的猫,狗才是具体的动物。
- 同理,我们不应该在动物类中给出具体体现,而是应该给出一个声明即可。类中如果有抽象方法,该类必须定义为抽象类。
-
抽象类特点
- 抽象类和抽象方法必须用abstract关键字修饰
抽象类格式: abstract class 类名 {}
抽象方法格式: public abstract void eat(); - 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
- 抽象类中可以有构造方法,用于子类访问父类数据时的初始化
- 抽象类按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
- 抽象类的子类
- 要么是抽象类
- 要么重写抽象类中的所有抽象方法
- 抽象类和抽象方法必须用abstract关键字修饰
-
案例演示
public class MyTest2 { public static void main(String[] args) { //抽象类,不能直接创建对象 } } abstract class Fu { public abstract void hehe(); public abstract void haha(); } class AA extends Fu {//空实现 public void hehe() { } public void haha() { } } abstract class CC extends Fu { public abstract void cc(); }//自己就是一个抽象类
-
抽象类的成员特点
-
成员变量:既可以是变量,也可以是常量。
-
构造方法:用于子类访问父类数据的初始化。
-
成员方法:既可以是抽象的,也可以是非抽象的。
-
案例演示
public class MyTest { public static void main(String[] args) { A a = new B(); System.out.println(a.num); } } //虽然抽象类不能new对象,但是可以通过多态对其成员变量赋值 abstract class A { int num = 20; public static int a = 200; public final int c = 20; public A() { System.out.println("父类的空参构造执行了"); } } //抽象类也有默认的空参构造 class B extends A { }
-
-
-
抽象类的成员方法特性
- 抽象方法 强制要求子类做的事情。
- 非抽象方法 子类继承的事情,提高代码复用性。
-
案例演示
- 假如我们在开发一个系统时需要对员工(Employee)类进行设计,员工包含3个属性:姓名、工号以及工资(salary)。
经理(Manager)也是员工,除了含有员工的属性外,另为还有一个奖金(bonus)属性。
然后定义工作的方法.
请使用继承的思想设计出员工类和经理类
- 假如我们在开发一个系统时需要对员工(Employee)类进行设计,员工包含3个属性:姓名、工号以及工资(salary)。
public class Mytest {
public static void main(String[] args) {
Employee e=new Manager();
e.age=40;
e.name="XX";
e.salary=9000;
System.out.println(e.age);
System.out.println(e.name);
System.out.println(e.salary);
e.work();
Manager m=(Manager) e;
m.bonus=10000;
System.out.println(m.bonus);
}
}
class Employee{
String name;
int age;
int salary;
public void work(){
System.out.println("敲代码");
}
}
class Manager extends Employee{
int bonus;
public void work(){
System.out.println("喝茶");
}
}
4.抽象类中的面试题
- 面试题1
一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
答案: 可以 . 不能创建对象. - 面试题2
abstract不能和哪些关键字共存?
private 冲突
final 冲突
static 不能共存 无意义
5.接口的概述
-
接口概述
为了体现事物功能的扩展性,Java中就提供了接口来定义这些额外功能,并不给出具体实现,将来哪些猫狗需要被培训,只需要这部分猫狗把这些额外功能实现即可 -
接口特点
-
接口用关键字interface表示 interface 接口名 {}
-
类实现接口用implements表示 class 类名
implements 接口名 {}
-
接口不能实例化
可以按照多态的方式来实例化。 -
接口的子类
- 可以是抽象类(无意义)
- 可以是具体类。要重写接口中的所有抽象方法。
-
案例演示
public interface JumpInterface { public abstract void jump(); }
-
-
接口的成员特点
-
成员变量:只能是常量,并且是静态的。
默认修饰符:public static final -
构造方法:接口没有构造方法。
-
成员方法:只能是抽象方法。
默认修饰符:public abstract
建议:自己手动给出。 -
案例演示
public class Dog extends Animal implements JumpInterface { @Override public void jump() { System.out.println("跳高"); } @Override public void eat() { System.out.println("骨头"); } } public class MyTest { public static void main(String[] args) { Dog dog = new Dog(); //父类 extends 子类 Animal an = dog; an.eat(); //父接口 implements 子类 JumpInterface jumpInterface = dog;//Dog子类实现了接口,所以必须指向子类 jumpInterface.jump(); } }
-
6.类与类,类与接口,接口与接口的关系
-
类与类:
继承关系,只能单继承,可以多层继承。 -
类与接口:
实现关系,可以单实现,也可以多实现。
并且还可以在继承一个类的同时实现多个接口。 -
接口与接口:
继承关系,可以单继承,也可以多继承。 -
JDK1.8之后对接口有所改变,可以给出方法的具体实现
interface A{ public default void cc(){//加入关键词default System.out.println("kk"); public static void ff(){//加入关键词static System.out.println("gg"); } }
7.抽象类和接口的区别
-
成员区别
- 抽象类
- 成员变量:可以变量,也可以常量
- 构造方法:有
- 成员方法:可以抽象,也可以非抽象
- 接口:成员变量只可以常量
成员方法只可以抽象(JDK1.8之前)
- 抽象类
-
关系区别
- 类与类 继承,单继承
- 类与接口 实现,单实现,多实现
- 接口与接口 继承,单继承,多继承
-
设计理念区别
- 抽象类 抽象类中定义的是该继承体系的共性功能。
- 接口 接口中定义的是该继承体系的扩展功能。
-
猫狗案例加入跳高功能分析及其代码实现
//动物父类
public abstract class Animal {
String name;
int age;
public abstract void eat();
public abstract void sleep();
}
//猫子类
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("c");
}
@Override
public void sleep() {
System.out.println("s");
}
}
//狗子类
public class Dog extends Animal {
public void eat() {
System.out.println("c");
}
public void sleep() {
System.out.println("s");
}
}
//二哈孙子类
public class 二哈 extends Dog implements JumpInterface {
@Override
public void eat() {
System.out.println("高级狗粮");
}
@Override
public void sleep() {
System.out.println("睡的是床");
}
@Override
public void jump() {
System.out.println("学会了跳高");
}
}
//加菲猫孙子类
public class 加菲猫 extends Cat implements JumpInterface {
public void eat() {
System.out.println("吃的鱼罐头");
}
public void sleep() {
System.out.println("睡沙发");
}
public void jump() {
System.out.println("学会了跳高");
}
}
//测试
public class MyTest {
public static void main(String[] args) {
加菲猫 jf = new 加菲猫();
jf.name = "加菲猫";
jf.age = 20;
System.out.println(jf.name);
System.out.println(jf.age);
cat = jf;
cat.eat();
cat.sleep();
JumpInterface jumpInterface = jf;
jumpInterface.jump();
二哈 eh=new 二哈();
eh.name="二哈";
eh.age=10;
JumpInterface ji= eh;
ji.jump();
}
}