Java是我职业生涯中最早接触的编程语言。它在我早期学习编程概念时奠定了基础。在学习了几种截然不同的语言之后,我的视野因此变得更加宽广。今天,我想谈谈“继承”这个概念。
Java中的继承在Java中在 Java 中,_继承_的概念与_子类型_的概念紧密相关。子类型体现了_是_的关系。例如,Rabbit
类是 Mammal
类的一种。因此,一个 Rabbit
实例继承了 Mammal
的所有行为:它继承了这些行为。
因此,当你需要传递一个 Mammal
参数时,你可以传递一个 Rabbit
实例;或者当你需要返回 Mammal
类型时,你可以返回一个 Rabbit
实例。你如果学过 Java、.Net 或类似的语言,这就是你理解继承的方式,也就成了你的新习惯。
这叫做明确的继承。
class Animal {
void feed();
}
class Rabbit extends Animal { //1
}
全屏 退出全屏
- 因为
Rabbit
是Animal
,所以它可以feed()
Go语言中的继承是如何实现的?
当我第一次接触 Go 时,我惊讶地发现它没有子类型,却仍然支持继承。Go 采用的是鸭子类型。
看起来像鸭子,游起来像鸭子,叫声像鸭子,那它大概就是鸭子。
如果一个 Go struct
实现了 interface 中的所有函数,它隐式实现了 interface。
type Animal interface {
feed() //1
}
type 兔 struct {
}
func (r *兔) feed() { //2
// 饲喂兔子
}
点击这里进入全屏模式,点击这里退出全屏模式。
- 一个
Animal
可以吃 - 因为存在一个
feed()
函数,它接受一个Rabbit
作为参数,因此Rabbit
继承了Animal
的特性。
我不是很喜欢Go处理错误的方式,但对隐式实现我有些犹豫。一方面,我尝试保持开放的态度;另一方面,我认为无论是编程还是生活中,事情总是明说比不说好。
Python中的继承特性Python 是我所知道的,关于继承最有趣的语言。
子类型和基于类型的继承特性自 Python 初创以来就一直存在。
class Animal:
def feed(self): #1 饲喂
pass #2 待实现
class Rabbit(Animal): #3 兔子
pass
进入全屏、退出全屏
- 一个
Animal
能吃 - Python 中没有抽象类,只有类
- 因为
Rabbit
是Animal
,所以Rabbit
也能吃
在这方面,Python 和 Java 在继承方面的运作方式相同。Python 还提供了动态类型,我把它称为 魔术方法。例如,为了使某东西可迭代,即能够返回一个迭代器,你只需要实现 __iter__()
和 __next__()
即可:
class SingleValueIterable():
done = False
def __init__(self, value):
self.value = value
def __iter__(self): #1
# 返回自身作为迭代器
return self
def __next__(self): #1
# 检查是否已完成迭代
if self.done:
# 抛出StopIteration异常表示迭代完成
raise StopIteration()
else:
# 标记迭代完成并返回值
self.done = True
return self.value
svi = SingleValueIterable(5)
sviter = iter(svi) #2
# 获取迭代器实例
for x in sviter:
print(x) #3
# 遍历迭代器并打印每个值
# 打印当前值。
全屏进入 退出全屏
- 动态类型检查方法
- 创建一个
Iterator
- Python 自动识别,因为我们已经实现了上述方法。 - 输出
5
这种鸭子类型的这种做法的问题是,它只能用于Python的预定义特殊方法(如__init__
、__str__
等)。如果你想提供一个类,让第三方可以隐式地继承自它,又应该怎么办?
class Animal:
def feed(self):
pass
class 兔子类:
def feed(self):
pass
全屏模式:进入 退出
在上述片段中,Rabbit
并不是 Animal
,这真让我们感到遗憾。这时引入了 PEP 544,名为“协议:结构次类型(静态鸭子类型)”。该 PEP 解决了我们类无法定义魔法方法的问题。它定义了一个简单的 Protocol
类:一旦从中继承,这些方法就可以进行静态鸭子类型检查,因此得名“静态鸭子类型”。
from typing import Protocol
class Animal(Protocol): #1
def feed(): #2
pass
class 兔子类:
def feed(): #2
pass
class 捕蝇草:
def feed(): #2
pass
进入全屏 退出全屏
- 继承自
Protocol
- 因为
Animal
是一个Protocol
,任何定义了feed()
的类都将被视为Animal
,好坏自明
面向对象编程、继承和子类型可能具有特定含义,这些含义在不同语言中可能有所不同,这取决于你最初学习的是哪种语言。Java 称自己为面向对象语言,并提供了完整的面向对象特性。Go 并不是一种面向对象语言,但它仍然通过鸭子类型实现了类似子类型的功能。Python 支持显式和隐式的继承机制,但不支持类似Java的接口。
你可以通过将新编程语言与已知语言进行比较来学习它。了解一种语言的特性对于用目标语言编写地道代码至关重要。熟悉那些在你已知语言中不存在的特性:这将拓宽你对编程的整体理解。
再往前走:
此处省略内容
_原文发表于A Java Geek 1月26日, 2025年
[OO: 面向对象]
共同学习,写下你的评论
评论加载中...
作者其他优质文章