// Interface
interface Animal {
public String name = "animal";
public void animalSound(); // interface method (does not have a body)
public void sleep(); // interface method (does not have a body)
}
// Pig "implements" the Animal interface
class Pig implements Animal {
public void animalSound() {
// The body of animalSound() is provided here
System.out.println("The pig says: wee wee");
}
public void sleep() {
// The body of sleep() is provided here
System.out.println("Zzz");
}
}
class Main {
public static void main(String[] args) {
Pig myPig = new Pig(); // Create a Pig object
myPig.animalSound();
myPig.sleep();
}
}
如果修改为Go语言实现,则为
type Animal interface {
animalSound();
sleep();
}
type Pig struct {
name string
}
func (p Pig) animalSound() {
fmt.Println("The pig says: wee wee")
}
func (p Pig) sleep() {
fmt.Println("Zzz")
}
func main() {
p := Pig{"pig"}
p.animalSound()
p.sleep()
}
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
鸭子类型(英语:duck typing)在程序设计中是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决定。这个概念的名字来源于由詹姆斯·惠特科姆·莱利提出的鸭子测试。
简单来说,不关注鸭子,而关注是否会呱呱叫。
在常规类型中,我们能否在一个特定场景中使用某个对象取决于这个对象的类型,而在鸭子类型中,则取决于这个对象是否具有某种属性或者方法——即只要具备特定的属性或方法,能通过鸭子测试,就可以使用。
这不禁让我让我想到两句谚语:狗拿耗子多管闲事和黑猫白猫能抓到耗子就是好猫。显然,这里要表达的意思和Duck Typing类似:只要够能抓住耗子,狗也可以是只猫。
不同于强类型语言,在实际使用Duck Typing时,只需要对象拥有这个方法即可调用,而不需要关心这些对象是否为同一类或继承类,比如Python内置的len()方法,本质上是在类中实现了__len__方法。
class DuckTypingDemo:
def __len__(self):
return 4096
duck_typing = DuckTypingDemo()
print("DuckTypingDemo len =", len(duck_typing))
# DuckTypingDemo len = 4096
my_str = "hello, world"
print("String len =", len(my_str))
# String len = 12
my_list = [1, 2, 3, 4, 5, 6]
print("List len =", len(my_list))
# List len = 6
my_dict = {"one" : 1, "two" : 2}
print("Dict len =", len(my_dict))
# Dict len = 2
try:
my_int = 6
print("int class =", my_int.__class__.__name__)
print("int len =", len(my_int))
except Exception as e:
print("Failed Reason:", e)
# int class = int
# Failed Reason: object of type 'int' has no len()
当我们为自定义类DuckTypingDemo定义了__len__方法时,就可以调用len方法,同理在内置函数中,对于string, list和dict也可以通过len获取相应类型的长度。
而对于没有定义__len__的int类型来说,就无法使用len方法获取其长度了。当然我们可以通过继承int,实现其__len__后,就可以使用len()方法了。
class IntWithLen(int):
def __len__(self):
return 1024
i = IntWithLen()
print("Int with length:", len(i))
# Int with length: 1024