多态的概念和实现
多态:一个事物在不同状态下的多种状态
举例:
- 学生是人,教师是人,医生是人。 (人在不同职业下的不同状态)
- 汽态的水,液态的水,固态的水。 (水在不同状态下的不同状态)
实现多态的前提:
1、必须要有继承关系
2、需要有方法的重写 (不是必须要重写,但是重写可以体现子类的专属特征,因为子类可能会有自己的成员对象)
3、要有父类的引用指向子类对象
注意事项:
- 1、必须是继承关系的类,才可以写成父类的引用指向子类对象
eg.GuTaiWater extends Water
固态水 继承于 水
Water w1 = new GuTaiWater() 正确
Demo1 w2 = new GuTaiWater() 错误
- 2、左边的父类可以不必是子类对象的直接父类,也可以是父类的父类
eg.Water extends Power
GuTaiWater extends Water
Power1 p1 = new GuTaiWater() 正确
多态下,访问成员的特点
1、成员变量
- 编译的时候,看左边的父类是否有该变量的存在,若存在,编译不报错,运行的结果也是取父类中该变量的值 (编译看左,运行看左)
2、成员方法
- 编译的时候,看左边的父类是否有该方法的存在,若存在,编译不报错,运行的结果取决于子类中该方法的实现 (编译看左,运行看右)
3、静态的成员变量
- 编译的时候,看左边的父类是否有该变量的存在,若存在,编译不报错,运行的结果取决于父类中该变量的值 (编译看左,运行看左)
多态的好处
1、提供了程序的维护性(由继承保证)
2、提高了程序的扩展性(由多态保证)
- 举例: 编写一个animal类,成员变量有姓名、年龄 ,成员方法有吃、睡,定义一个工具类对每个动物调用吃和睡功能
class Animal{
String name;
int age;
public Animal(){
//无参构造方法,可以让下面的子类不需要定义构造方法
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void eat(){
System.out.println("我饿了,我吃饭");
}
public void sleep(){
System.out.println("我困了,我睡觉");
}
}
class dog extends Animal{
@Override
public void eat() {
System.out.println("🐕吃🥩");
}
@Override
public void sleep() {
System.out.println("四仰八叉着睡");
}
}
class cat extends Animal{
@Override
public void eat() {
System.out.println("🐱吃🐟");
}
@Override
public void sleep() {
System.out.println("也四仰八叉着睡");
}
}
class AnimalTool{//工具类
private AnimalTool(){};
public static void useAnimal(Animal animal){//工具类应当尽量避免修改,这里使用static修饰,表示静态的
animal.eat();
animal.sleep();
}
}
public class test {
public static void main(String[] args) {
//这里是工具类的引用语句
dog d1 = new dog();
AnimalTool.useAnimal(d1);
cat c1 = new cat();
AnimalTool.useAnimal(c1);
//这里是多态实现语句,同样也可以实现
//Animal d2 =new dog();
}
}
运行结果
多态访问成员方法的弊端
- 多态的形式下,无法调用子类中特用的方法
解决方案:向下转型
语句定义格式:
子类的类型 对象名 = (子类的类型) 父类的变量
父类A 子类B
A a = new B();
B b = (B) a;
abstract(抽象的):
可以修饰类、成员方法
使用的注意事项:
1、抽象类不能进行实例化
2、抽象类中即可以存在具体的方法,也可以存在抽象的方法
具体的方法:指的是方法大括号方法体 eg. eat(){...}
抽象的方法:指的是方法被abstract关键字修饰,没有具体的实现,连大括号都没有
3、抽象的可以被具体的类继承,但是如果是被具体的类继承的话,必须要重写所有抽象类中所有的方法
4、抽象类A继承抽象类B时,可以选择是否重写抽象方法
5、抽象类无法进行实例化,但是却可以拥有构造函数,这样的意义是为了将来父类做初始化,因为子类构造方法默认是super()
6、抽象类中可以存在变量、常量、静态的变量
abstract不能与哪些关键字共存?
private
冲突
private修饰的方法不能被子类继承,但是abstract方法将来要被重写final
冲突
final修饰的方法是不能被子类重写的,而abstract方法将来要被重写static
无意义
static属于类本身,不是类的实例,它们可以在创建类的实例的情况下被调用,与类的实例化无关,它们不是抽象的,静态方法在继承中的行为与实例方法不同,不会被子类重写,而是隐藏或被子类的静态方法覆盖
以后我们常见的组合:- public static
- public abstract
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现