Java第六篇:Java抽象类和抽象方法

张开发
2026/4/21 21:06:45 15 分钟阅读

分享文章

Java第六篇:Java抽象类和抽象方法
目录前言:引入抽象类:胡辣汤的启示为什么妈妈的汤不能直接喝问题为什么不能直接喝“煮到一半的汤”什么是抽象类what 妈妈的“基础汤”什么是抽象方法(what) “加胡椒粉”这个行为多学亿招:注意事项抽象类与抽象方法的“雷区”解析1. 抽象类可以没有抽象方法2. 抽象方法一定有抽象类3. 抽象类可以包含什么总结前言:今天我们来学习关于抽象(abstract)内容,包括抽象类和抽象方法。引入抽象类:胡辣汤的启示为什么妈妈的汤不能直接喝生活场景今天我和弟弟想喝胡辣汤。我嚷嚷着“要多放胡椒粉辣得过瘾”弟弟却小声说“少放点温和点就好。”妈妈开始煮汤汤在锅里咕嘟咕嘟冒泡煮到一半时她突然关火把汤舀出来放在一旁说“底料好了但胡椒粉得按你们的口味加”于是妈妈把汤“暂停”了——她不能直接端出这碗“半成品”汤让我们喝因为胡椒粉量没定而是让我们各自加料我多加一勺弟弟少加半勺。加完后汤重新下锅继续煮。最终我喝到的是“超辣胡辣汤”弟弟喝到的是“微辣胡辣汤”。这就是抽象类和抽象方法!问题为什么不能直接喝“煮到一半的汤”因为汤不完整妈妈的“胡辣汤”缺少了关键细节——胡椒粉的量。如果强行喝它要么太辣像我要么太淡像弟弟但妈妈的汤本身没有指定这个细节。类比到代码一个类如果缺少关键行为如“怎么加胡椒粉”它就不能代表一个具体对象而只能作为“模板”———当一个类中给出的信息不够全面时比方说有无法确定的行为它给出的信息不足以描绘出一个具体的对象这时我们往往不会实例化该类这种类就是抽象类。从胡辣汤场景看本质:什么是抽象类what 妈妈的“基础汤”定义用abstract修饰的类不能被实例化new AbstractSoup()会报错。为什么妈妈的“基础汤”不能直接喝——因为它信息不全缺少胡椒粉量。同理Java 中的抽象类不能实例化因为它缺少关键实现如抽象方法。什么是抽象方法(what) “加胡椒粉”这个行为定义用abstract修饰且无方法体的方法如public abstract void addPepper();。为什么妈妈说“加胡椒粉”但没说加多少——这个行为必须由我们子类来决定。同理抽象方法定义“做什么”加胡椒粉但不定义“怎么做”多/少。关键类比表格生活场景Java 代码妈妈的“基础汤”abstract class AbstractSoup“加胡椒粉”行为abstract void addPepper()我的“多加胡椒粉”class MeSoup extends AbstractSoup弟弟的“少加胡椒粉”class BrotherSoup extends AbstractSoup上代码:首先定义父类,抽象类,抽象方法———妈妈做汤给我和弟弟的汤的步骤// 抽象类妈妈的基础汤不能实例化 public abstract class AbstractSoup { public void cookBase() { // 通用步骤煮底料 System.out.println(煮底料中...汤已煮到一半); } // 抽象方法必须由子类实现 public abstract void addPepper(); // “加胡椒粉”行为具体量由子类定 //通用步骤,放完胡椒粉,继续煮汤 public void cookend(){ System.out.println(再煮五分钟...汤煮完了); } }// 我的版本多加胡椒粉子类必须实现抽象方法 //子类继承父类,并重写抽象方法addPepper public class MeSoup extends AbstractSoup { Override public void addPepper() { System.out.println(多加一勺胡椒粉辣到流泪); // 我的实现 } } // 弟弟的版本少加胡椒粉子类必须实现抽象方法 //子类继承父类,并重写抽象方法addPepper public class BrotherSoup extends AbstractSoup { Override public void addPepper() { System.out.println(少加半勺胡椒粉。); // 弟弟的实现 } }// 测试妈妈的“基础汤”不能直接用 public class Main { public static void main(String[] args) { AbstractSoup mySoup new MeSoup(); // 父类引用指向子类对象 mySoup.cookBase(); // 输出煮底料中...汤已煮到一半 mySoup.addPepper(); // 输出多加一勺胡椒粉辣到流泪 mySoup.cookend(); //输出:再煮五分钟...汤煮完了 AbstractSoup brotherSoup new BrotherSoup(); brotherSoup.cookBase(); // 输出煮底料中...汤已煮到一半 brotherSoup.addPepper(); // 输出少加半勺胡椒粉。 brotherSoup.cookend(); //输出:再煮五分钟...汤煮完了 } }多学亿招:用final关键字修饰模版方法,为什么模版方法是给子类直接用的,不能被子类重写。一旦子类重写了模版方法模版方法就失效了。如下public abstract class AbstractSoup { // 重要煮底料步骤是通用且不可变的加 final public final void cookBase() { // 通用步骤煮底料 System.out.println(煮底料中...汤已煮到一半); } // 重要:不能加 final抽象方法必须由子类实现! public abstract void addPepper(); // “加胡椒粉”行为具体量由子类定 //重要煮最后汤步骤也是通用且不可变的加 final public final void cookend(){ System.out.println(再煮五分钟...汤煮完了); } }千万注意抽象方法不能再使用privatefinal或者static关键字来修饰即abstract不能与privatefinal或static共同出现这是因为定义抽象方法的目的就是想将方法的具体实现延迟到子类最终是要被子类重写的而privatefinalstatic这几个关键字都和“方法重写”的目的背道而驰。注意事项抽象类与抽象方法的“雷区”解析1. 抽象类可以没有抽象方法为什么抽象类的核心是“不能被实例化”new AbstractSoup()会报错而非“必须有抽象方法”。妈妈的“汤底”抽象类可以包含所有步骤如默认加胡椒粉但不能直接喝因为它是概念不是具体汤。public abstract class AbstractSoup { // 通用步骤煮底料具体方法 public void cookBase() { System.out.println(煮底料中...汤已煮到一半); } // 默认加胡椒粉具体方法无需子类重写 public void addPepper() { System.out.println(默认加一勺胡椒粉。); // 所有汤都默认加一勺 } // 通用步骤煮最后具体方法 public void cookend() { System.out.println(再煮五分钟...汤煮完了); } } // 子类无需实现抽象方法 public class DefaultSoup extends AbstractSoup { // 无需重写 addPepper()因为父类已提供默认实现 }妈妈说“汤底已经加好胡椒粉了你们爱喝不喝。”无需子类实现addPepper2. 抽象方法一定有抽象类为什么抽象方法的语义是“子类必须实现”而具体类非抽象类可以被实例化无法保证子类实现。如果妈妈在“具体汤”非抽象类中声明“加胡椒粉”是抽象的那她根本没法煮汤public class Soup { // 非抽象类不能是抽象类 public abstract void addPepper(); // ❌ 编译错误抽象方法不能在非抽象类中 }也就是说拥有抽象方法的类一定是抽象类但是抽象类不一定有抽象方法3. 抽象类可以包含什么抽象类是“有状态的模板”能包含所有类成员但不能实例化表格成员类型说明胡辣汤类比字段实例变量状态如private int temperature;汤的温度妈妈的汤底有温度构造方法用于子类初始化super()如public AbstractSoup(int temp)妈妈煮汤时设置初始温度具体方法有实现的方法子类可直接使用煮底料cookBase、煮最后cookend抽象方法无实现的方法子类必须重写加胡椒粉addPepper静态方法类方法与实例无关如public static void printInfo())妈妈的汤底说明“所有汤底通用”总结抽象类 妈妈的汤底不能直接喝但能提供通用步骤有字段汤的状态温度、浓度有构造方法初始化汤的状态有具体方法煮底料、煮最后通用步骤有抽象方法加胡椒粉必须由子类定制三个字啥都行最后叮嘱“抽象类不是接口的替代品而是有状态的接口。”用好抽象类让代码像妈妈的胡辣汤一样——基础扎实定制灵活下次煮汤时记得说“妈妈这个汤底是抽象类我来实现 addPepper()” 总结今天我们通过胡辣汤学习到了什么是抽象类什么是抽象方法。本次分享到此结束感谢大家的观看与支持如果本内容对您有帮助欢迎点赞、收藏您的支持将是我持续创作的最大动力谢谢

更多文章