Abstract Classes Part 1
来自 Tim Buchalka 的免费视频教程
Java Python Android and C# Expert Developer - 1.73M students
15 门课程
1787858 名学生
讲座描述
Get to know more about Abstraction in this lecture.
通过完整课程学习更多知识
Java Masterclass 2025: 130+ Hours of Expert Lessons
Gain real-world experience with OOP, coding exercises, and problem-solving for job-ready Java development skills
135:12:14的随选视频 • 更新于 August 2026
Learn the core Java skills needed to apply for Java developer positions in just 14 hours.
Be able to sit for and pass the Oracle Java Certificate exam if you choose.
Be able to demonstrate your understanding of Java to future employers.
Learn industry "best practices" in Java software development from a professional Java developer who has worked in the language for close to 25 years.
Acquire essential java basics for transitioning to the Spring Framework, Java EE, Android development and more.
Obtain proficiency in Java 17, as well as older versions incluing Java 11 and Java 8.
Java 21 features coming soon!
简体中文 [自动]
所以在这组视频中我们要
开始谈论抽象。 所以抽象就是当你定义 所需的功能, 而实际上 落实细节。 换句话说, 我们正在关注 该做什么而不是该怎么做 如你所见, 界面是 都是纯粹抽象的, 它们并没有具体说明 执行的方面。 当然, 实际的实现留给了 实现接口, 这就是为什么我们使用implements这个词 when we're using运用an interface接口. 你也看到了, 我有挑战
从视频的接口集合。 我就这么一遍一遍地
再确认一下 所以你可以看到
这里有我们的接口。 这是一个界面
最初有数组列表。 如果你记得我改了名字 返回到一个列表, 我在这里把它改回ArrayList 再多说一点 但是, 再次回到接口, 接口定义了 该做什么。 它没有定义它是如何完成的。 如何,
我们得走进教室 在这种情况下说怪物, 和 它实际上实现了Isavable接口 它真的会起作用 而我们得到了 错误, 因为你还记得我们 实际上把它变成了一个列表。 但我故意改变了界面 回到数组列表, 因为我想谈谈这个 所以ISaveable接口 正如你在屏幕上看到的, 提供或指定必须有 一个返回要保存的值的ArrayList的write方法, 以及读取方法。 正如你在屏幕上看到的, 要恢复的值的ArrayList。 所以没有其他细节 类应该如何填充, 或者编写ArrayList。 没有关于类应该做什么的细节 也不处理读取值, 这完全保留 每一个单独的班级。 你真的可以如果你想…设置它 这样每个实现这个接口的类可以做完全不同的事情 使用write和read方法。 做什么没有规则
使用这些方法和接口。 这些方法必须
在特定的类中实现。 但严格来说, 如果你看这个
接口, 它不是完全的抽象。 原因是在这种特殊情况下, 有一个规范 必须使用数组列表。 但在Java这样的类型化语言中
有时难免会这样。 但在这个特殊的例子中, 我在 在前一个质询中, 接口质询, 我们可以将其抽象化, 只使用一个List。 所以我们能做的 我们本可以改变的, 我们所做的就是改变它, 所以我们实际上去掉了对ArrayList的需求, 实际上只是改变了 事实上, 它只是一个列表。 通过这样做, 我们又抽象了, 因为我们没有强迫怪物 类或Player类或实现此 接口必须使用ArrayList。 他们可以使用任何类型的列表
这很重要。 这真的很有用 我已经提出了一个建议, 无论何时使用列表, 都应该这样做 在你的程序中。 一般来说在 声明的条款, 这样写很好 这使得您的实现可以实际使用任何类型的 是实现该特定接口的任何东西, 在这种情况下 列表接口是Java的一部分。 简单回顾一下, 我们可以看到如果我们 实际上点击这个, 我按住命令, 我相信它是Alt在你的 控制, 对不起, 在Windows机器上。 点击它, 我们就可以进入实际 列表接口是Java的一部分, 实际上非常有趣 读一些代码 你可以看到这实际上是 列表的公共接口, 其他类(如 Java中的数组列表等。 实际上必须实现
实际使用。 很明显根据定义, 作为一个接口是抽象的, 所以你不能使用一个新的ISAvable或 一份新名单 你需要做的是实例化
实现接口的类。 你显然也看到了
在界面挑战赛中。 Java也允许抽象类。 在我们深入讨论之前 我只想更进一步, 提到这个界面, 我们其实可以更进一步, 因为我们 指定类型为字符串。 但如果我们真的想 灵活, 我们甚至可以删除它, 并使其成为一个真正的通用列表。 并将其留给用户, 实现这个接口的类来决定 实际使用的类型。 所以我很乐意这么做, 然后我们可以回到我们的怪物类, 要改变它, 我们就必须改变一些小东西 用定义的术语。 但最终你可以 考虑到额外的功能, 或者额外的灵活性, 我应该说对于我们正在使用的实际类来说 在这个接口中实现。 所以记住这点你可以承受 如果你想更进一步 给自己最大的灵活性。 但有时候会有一点罚款 行, 以了解您如何使其通用和如何具体。 有时候, 就在某个地方
中间可能是个好办法。 正如我提到的, 接口是由
定义, 在Java中, 抽象。 因此, 您无法使用新的ISAvable或
新名单 你必须…实例化一个类 接口, 它实现了我应该说, 接口。 我要做的就是 我现在要把这个关了, 我要换掉, 因为我创造了 IntelliJ for Abstraction中的新项目。 我们真的要
开始输入一些代码 因为正如我提到的,
Java也支持抽象类。 这些类定义了方法 但不提供实现 这些方法。 实现本身就剩下了 抽象类继承的类。 所以这和
从接口继承。 也可以继承自
一个真正的班级。 所以在继承的视频里 创建了一个非常基本的动物类, 然后我们扩展它来创建一个狗。 看看我们能不能做点什么
现在类似, 使用抽象类。 所以我现在要敞开心扉
然后创建一个新类。 Java类, 以及
我会叫它动物。 我要做的就是
把它变成一个抽象类。 为此我们输入单词
在我们的修饰符之后抽象。 抽象类Animal
我们可以定义变量。 所以我们只需要输入private String name, 我们就可以有一个构造函数, 它 我们会把动物的名字传给我们 我们再加上几个 额外的抽象方法, 这是我想给你们看的部分 吃和呼吸。 所以我们可以把public abstract和abstract关键字放在 修饰符void eat注意我们在这里加了分号 所以我们根本没有实现这个。 和公共抽象的虚空呼吸。 我们还可以添加一个构造函数。 对不起, 我们还可以添加一个getter
我应该说, 名字。 所以有一个抽象类 你可以看到我们正在做的是, 正如我们将要看到的, 我们要 继承自这个抽象类。 它会让我们定义 行为是必要的, 而不指定如何 它们将被执行。 这确实确保了 子类, 比如dog, 必须实际实现它们, 因为 当然, 通常, 在普通类中, 如果你从一个类扩展, 你可以在类中创建一个基方法。 但没有要求 另一个类, 即子类化到的类 真正实现这些方法。 但是通过创建抽象方法, 我们实际上是强制类 最终将从这个抽象类实现来创建这些方法 我们。 这就是为什么我们
把它们标记为抽象的。 其他方法和其他领域 在这种情况下, 它们可以像普通Java代码一样工作。 但我们实际上是在指定和说有一些抽象方法 在这里必须执行。 所以如果你真的提到 回到继承的视频, 你会发现这是 非常相似。 唯一的区别是 实际上把它标记为抽象的, 实际的类定义 在顶部。 我们还包括了
抽象方法也是。 在这个例子中为了简单起见, 我实际上已经删除了成员变量, 如大脑, 体重等。 ,
只是为了让事情变得简单 现在如果我们真的试着从这里延伸
我想让你看看到底发生了什么。 所以我要创建一个新类
我要叫它狗。 我要伸展一下动物。 我想我已经把 动物放错了地方动物应该在包裹里 所以我得把它移开 拖动它然后
而是问我想把它移到哪里 我想把它移到那个包裹里,
所以我要点击重构。 现在应该能修好了所以
我们来对地方了 但现在你可以看到
另一种错误。 如果我们看一下, 它实际上告诉我们, 班级狗 必须声明为抽象, 或者需要实现抽象 方法在动物中食用。 实际上有两种方法 需要在那里实现, 但这个小错误消息是 只弹出第一个。 所以你可以看到现在为了能够创建一个有效的 类, 我们必须实现这些方法。 所以我们可以做一些像创建 构造函数, 像这样, 我们只使用默认的 super保存实际名称, 该名称位于animal类中。 我们现在可以做一些覆盖。 我们可以用Alt+N 去实现或覆盖, 它们实际上都 弹出同样的东西。 现在你可以看到
我有两个选择 我们有两个选择 请注意这里的小描述或小图标, 他们有点不一样 getName你可以看到
一种方法但这也是一种方法 但注意它是如何
一大块被切下来的肉 这是IntelliJ的说法
这是一个抽象的方法。 所以我可以选择这两个 重写它们, 然后使类有效并 我可以在代码里写点东西。 GetName +正在吃饭。 至于呼吸, 吸气, 呼气, 重复, 非常基本。 所以现在它是一个有效的
你可以看到的班级。 还要记住, 因为我们实现了 Animal类中的名称getName在这个类中是可用的 在这里用在了eat方法中。 同样, 从构造函数I 我提到我们实际上使用super关键字调用了构造函数, 它调用了 实际上在动物类中也是如此。 所以重要的是
并非所有方法都必须是抽象的。 这是其中一个区别 一个抽象类和一个接口, 你可以把它们混合起来。 如果你还记得的话,
如果你回去看看 实际上看起来 我结束了这个项目, 我也许应该换个工作。 但是使用以前的接口 你之前在视频中看到的, 整个界面是完全抽象的, 而且 根本没有实施。 所以没有机会
让我们进入领域。 没有任何机会
让我们输入任何其他代码。 我们只能简单地说明 这个接口要用到的方法 实现该特定接口必须实际实现 使其有效。 但你可以看到在动物的情况下,
我们实际上可以混合使用。 我们实际上可以添加字段。 我们可以添加常规方法, 或者
在这种情况下是一个构造函数。 但也是一种常规方法
可以看到这里的构造函数。 但我们也可以指定某些
方法是抽象的, 如你所见。 所以在实际使用的时候,
现在它的工作原理和你预期的一样。 所以如果你要写一些代码 我们可以这样做:Dog _dog = new Dog, Yorkie, dog。 呼吸。 再一次, 它表现,
你会觉得这会有用的 吃吧。 如果我真的运行它。 吸气, 呼气, 重复。 约克在吃饭, 所以 你可以看到一切都运行得很好, 就像你想象的那样。 好吧, 这就是你想的那样 但是现在让我们进入下一步, 实际上创建另一个类, 在这个例子中是鸟。 Java类, 以及
我们就叫它伯德 伯德和我们需要扩展, 因为 显然, 使用extends关键字, 因为它是一个类, 和Animal。 并创建构造函数, 它的工作原理和你想的一样, 让我们也重写这些方法。 吃和呼吸, 再次。 我们会把它当食物,
getName +正在啄食。 对于呼吸 都是一样的, 吸气, 呼气, 重复。 就像这样, 当然, 我们可以
回到我们的主类, main方法。 鸟, 鸟=新鸟。 小鸟。 呼吸。 小鸟。 吃吧。 你可以运行它。 我们得到了结果, 正如你所看到的。 鸟类呼吸, 以及
鹦鹉在啄, 约克在吃 所以它在做正确的事情。 现在鸟也能飞了, 所以添加一个可能是个好主意 一个fly方法到我们的bird类中。 但是, 并不是所有的鸟都能飞, 所以在 鸟类课不是个好主意 更好的主意是创建一个抽象的 继承Animal的Bird类, 还有一个抽象的fly方法 每个Bird对象都能实现的。 所以让我们继续
看看效果如何 所以我们现在就过去
修改Bird类。 把这个关上给我们一点空间。 现在我要把这个换一下 现在我们有了公共类Bird, 我会把它抽象化。 保持构造函数不变 保持两种方法不变, 但也要在底部, 让我们添加另一个抽象方法。 所以公共抽象虚空飞。 这是另一个抽象的概念
班级在这一点上 这是一个抽象类
是从另一个抽象类扩展而来的。 它正在实现所需的方法 Animal类要求它做的事情, 即吃和呼吸。 但它也定义了
一个抽象的方法飞。 最终必须被覆盖
也是另一个阶级。 当然我们把这个类设为抽象的, 它需要在其中 无论如何都要这样做。 现在我们已经完成了 当然我们回到主类, 我们会得到一个错误, 因为, 等等 我们可以看到错误是什么。 鸟是抽象的。 它不能实例化。 记得吗我们说过 在视频的前面, 您不能直接实例化 一个抽象的类。 所以我们要做的是
实际上是创建一个类。 为了做到这一点, 我们要改变这个, 然后
我们将创建一个Parrot类。 回到这里, 创建一个新类Parrot。 我们可以延伸, 延伸伯德,
没有构造器。 我们现在要做的, 是因为其他方法已经在Bird类中被覆盖了 我们只需要做一个 所以如果我们回到那里看一看, 然后转到覆盖, 我们仍然可以覆盖 如果我们想吃和呼吸, 如果出于某种原因这种鸟有 一种不同的饮食或呼吸方式。 但说真的我们只想 在本例中重写了fly, 以使该类有效。 所以我会这么做, 然后我会放一些像 在树枝间飞来飞去。 所以它实际上是在飞
从一个分支到另一个分支。 鹦鹉又自动继承了吃和 呼吸从, 和呼吸, 我应该说从鸟, 所以我们没有 重新实现这些方法。 它现在有了自己的实现
飞。 所以如果你现在回到main方法。 我们现在把它改成
实际上是鹦鹉而不是鸟 记住鹦鹉是
现在从鸟开始延伸。 Parrot设置为new Parrot, 并且 现在我们不输入Parrot作为名字, 而是说它是澳大利亚的ringneck, 那就是鹦鹉 呼吸。 这仍然会工作。 鹦鹉 吃吧。 但我们也要学鹦鹉。 现在就飞。 所以如果你运行它, 你可以看到
不再有错误了 你可以看到澳大利亚环颈犬正在啄食 在树枝间飞来飞去 再举一个例子 我们可以做一些不同的事情, 让我们再创建一个类。 新〉Java类和
我们就叫它企鹅 我们又从伯德开始延伸
从鸟延伸而来。 创建构造函数。 我们再重写一次飞行。 我们可以说我不擅长这个。 我可以去游泳吗? 这就是我们对penguin的实现。 所以再回到主方法, 我们可以直接下来 这里我可以写Penguin, penguin = new Penguin 皇帝和企鹅。 飞。 现在, 如果我们真的运行它。 你可以看到, 我们实际上得到了信息 很正确, 仍然, 在鸟类澳大利亚ringneck是 啄食, 从一个树枝飞到另一个树枝, 我们只打印出 企鹅的飞行方法。 我不太擅长这个
我能去游泳吗? 你可以看到
工作得很好。 所以我就在这里结束这段视频。 在下一个视频中 我要做的就是开始讨论这有什么不同 以及如何决定是否使用 接口或抽象类。 我们下一个视频再见。