为什么要有多态?(个人理解)
子类的特殊需求父类无法满足,需要重写对应的方法来满足子类的需求。这样的话我们创建的对象就会有各种各样的状态。例如:
什么是多态?
同一个对象,在不同时刻表现出来的不同形态
多态的前提
要有继承或实现关系
要有方法的重写
要有父类引用指向子类对象
成员访问特点
当对象创建格式为:
父类 变量 = new 子类()
成员变量 编译看父类,运行看父类
成员方法 编译看父类,运行看子类
因为父类的成员方法可能被子类重写,而成员变量不存在重写,所以不用考虑子类的成员变量。
举例:
class Person{
int age =40;
public void shows(){
System.out.println("我要吃面条");
}
}
class Hyg extends Person{
int age = 20;
@Override
public void shows(){
System.out.println("今天不吃面条了,吃饺子");
}
}
public class TestDemo {
public static void main(String[] args) {
Person hyg = new Hyg();
System.out.println(hyg.age);
hyg.shows();
}
}
结果:
40 //父类中的成员变量
今天不吃面条了,吃饺子 //执行了子类的成员方法
抽象类
个人理解:
既然父类无法满足子类的某些需求,当这种子类较多的时候就要写很多的重写方法。所以干脆父类不去实现这些方法,只给出这个抽象的行为,父类不去实现,由子类去实现。
抽象类的特点
1.抽象类和抽象方法必须使用 abstract 关键字修饰,否则就是普通的类和方法
//抽象类的定义public abstract class 类名 {}
//抽象方法的定义public abstract void eat();
2.抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
3.抽象类不能实例化 抽象类如何实例化呢?参照多态的方式,通过子类对象实例化,这叫抽象类多态
4.抽象类的子类 要么重写抽象类中的所有抽象方法 要么是抽象类
5.子类必须重写抽象类中的所有抽象方法,除非子类也是抽象类
6.抽象类除了不能实例化,其他性质和普通类一样。也有自己的构造方法,也可以通过类名去调用静态方法。
举例:
abstract class Person{
public Person(){
System.out.println("抽象类的构造方法");
}
abstract void show();
}
class Hyg extends Person{
public Hyg(){
System.out.println("子类的构造方法");
}
@Override
void show() {
System.out.println("重写父类中的show方法");
}
}
public class TestDemo {
public static void main(String[] args) {
Person hyg = new Hyg();
hyg.show();
}
}
输出
抽象类的构造方法
子类的构造方法
重写父类中的show方法
接口
(个人理解):抽象类里面又有普通方法,又有抽象方法。当方法比较多的时候,抽象方法和普通方法混在一起,不利于维护。为了更好的维护,干脆将抽象方法都集合到一起。也就是现在的接口。
抽象类有构造方法,并且子类只能继承一个父类,就像一个人只能有一个父亲一样。接口没有构造方法,子类可以实现多个接口,就像人可以穿多件衣服一样。
接口的概述:
接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。
Java中的接口更多的体现在对行为的抽象!
接口的特点
接口是一种没有构造方法的抽象类
接口用关键字interface修饰public interface 接口名 {}
类实现接口用implements表示public class 类名 implements 接口名 {}
接口的子类 要么重写接口中的所有抽象方法 要么子类也是抽象类
接口的成员特点
构造方法 没有,因为接口主要是扩展功能的,而没有具体存在
成员变量只能是常量(), 默认修饰符:public static final
(为什么只能是常量呢?因为不存在构造方法,也就无法实例对象,对象都没有怎么去获取对象的成员变量呢。所以它只能依赖类了,由于是公共使用的,总不能是谁都可以随意的修改的,所以必须被final修饰。)
举例:
interface Interface{
int a = 12;//默认被public static final修饰
}
interface Interface2{
int a = 23;
}
public class InterfaceTest implements Interface,Interface2{
public static void main(String[] args) {
System.out.println(Interface2.a);
}
}
//成员变量的访问也符合就近原则
//当子类只继承一个接口时,可以省略接口名直接使用接口的变量。
//当继承多个接口时,就需要接口名来区分变量了。
成员方法 只能是抽象方法 默认修饰符:public abstract,在JDK新特性中允许有默认的非抽象方法存在,当被默认修饰符修饰时,相当于继承一样了,可重写也可不重写。
下面这段代码没有重写接口的默认方法,并没有报错
当实现的多个接口中有重名的方法时,只会实现一个。并且如果同名方法的返回值不一样,出现歧义还会报错。
例如: