鸭子打字和(java)界面概念 [英] Duck typing and (java) interface concept

查看:136
本文介绍了鸭子打字和(java)界面概念的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚阅读了关于鸭式打字的维基百科文章,我觉得我错过了关于界面概念的重点我曾经在Java中:

 当我看到一只像鸭子一样走的鸟儿,像鸭子一样游泳,像鸭子,我把那只鸟叫做鸭子。 


class Duck:
def quack(self):
print(Quaaaaaack!)
def feathers(self):
打印(鸭子有白色和灰色羽毛)
def swim(self):
print(在水中无缝游泳)

class Person:
def quack(self):
print(该人模仿一只鸭子)
def羽毛(自):
print(该人从地面上展现羽毛,并显示
def name(self):
print(John Smith)

def in_the_forest(duck):
duck.quack()
duck.feathers()

def game():
donald = Duck()
john = Person()
in_the_forest(donald)
in_the_forest(john)

game()

如果,在code> in_the_forest ,我写道:




  • quack 像鸭子一样是

  • 是否有鸭子羽毛?是的

  • 很棒,我们有一只鸭子!



知道这是一只鸭子,我想要它游泳

我不希望我的应用程序在其进程中随机(随机)崩溃只是因为John伪造成一只鸭子,但是我猜想当我收到它时,检查对象的每一个属性都不是一个明智的主意。?

解决方案

鸭子打字不是真的关于检查你需要的东西是否在那里,然后使用它们。鸭子打字只是使用你所需要的。



in_the_forest 函数是由一个正在考虑鸭子。它被设计为在 Duck 上操作。 Duck 可以 quack 羽毛,所以编码器使用那些功能让工作得到了解。在这种情况下,没有使用 Duck 也可以游泳的事实,不需要。 / p>

在像Java这样的静态语言中, in_the_forest 将被声明为 Duck 。当编码器后来发现他们有一个 Person (也可以 quack 羽毛),并想重用该功能,他们没有运气。一个个人一个 Duck 的子类?不,这似乎不合适。有没有一个 QuacksAndFeathers 界面?也许,如果我们幸运的话。否则,我们必须做一个,去修改 Duck 来实现它,并修改 in_the_forest 来获取 QuacksAndFeathers 而不是 Duck 。如果 Duck 在外部库中,这可能是不可能的。



在Python中,您只需将您的Person传递给 in_the_forest ,它的工作原理。因为事实证明 in_the_forest 不需要 Duck ,它只需要一个鸭子对象,在这种情况下,人是足够的鸭子。



游戏虽然,需要一个不同的定义鸭子,稍微强一些。在这里,约翰·史密斯是幸运的。



现在,Java在编译时会遇到这个错误,Python不会。这可以被看作是一个缺点。 pro-dynamic-typing counter参数是说,您编写的任何大量代码将总是包含编译器可以捕获的错误(实际上,Java甚至不是一个特别好的例子的编译器,具有强大的静态检查以捕获大量的错误)。所以你需要测试你的代码来找到这些bug。如果您正在测试这些错误,您将轻而易举地发现您将 Person 传递给需要 Duck 。考虑到动态打字员说,一种引导你进入而不是测试的语言,因为它发现一些的微不足道的错误实际上是一个恶劣的事情。最重要的是,它阻止你做一些真正有用的事情,比如在 Person 上重用 in_the_forest 函数。



我个人被撕毁在两个方向。我真的很喜欢Python与其灵活的动态打字。而且我非常喜欢Haskell和 Mercury ,用于其强大的静态类型系统。我不是Java或C ++的粉丝;在我看来,他们有静态打字的所有坏点,几个很好的位。


I just read the Wikipedia article about duck typing, and I feel like I miss an important point about the interface concept I used to in Java:

"When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck."


class Duck:
    def quack(self):
        print("Quaaaaaack!")
    def feathers(self):
        print("The duck has white and gray feathers.")
    def swim(self):
        print("Swim seamlessly in the water")

class Person:
    def quack(self):
        print("The person imitates a duck.")
    def feathers(self):
        print("The person takes a feather from the ground and shows it.")
    def name(self):
        print("John Smith")

def in_the_forest(duck):
    duck.quack()
    duck.feathers()

def game():
    donald = Duck()
    john = Person()
    in_the_forest(donald)
    in_the_forest(john)

game()

what if, in in_the_forest, I write:

  • does it quack like a duck ? yes
  • does it have a duck feathers ? yes
  • great, it's a duck we've got !

and later, because I know it's a duck, I want it to swim? john will sink!

I don't want my application to crash (randomly) in the middle of its process just because John faked to be a duck, but I guess it wouldn't be a wise idea to check every single attributes of the object when I receive it ... ?

解决方案

Duck typing isn't really about checking whether the things you need are there and then using them. Duck typing is about just using what you need.

The in_the_forest function was written by a developer who was thinking about ducks. It was designed to operate on a Duck. A Duck can quack and feathers, so the coder used those features to get the job at hand done. In this case, the fact that a Duck can also swim wasn't used, and wasn't needed.

In a static language like Java, in_the_forest would have been declared to take a Duck. When the coder later discovered that they had a Person (which could also quack and feathers) and wanted to reuse the function, they're out of luck. Is a Person a subclass of Duck? No, that doesn't seem at all appropriate. Is there a QuacksAndFeathers interface? Maybe, if we're lucky. Otherwise we'll have to make one, go modify Duck to implement it, and modify in_the_forest to take a QuacksAndFeathers instead of a Duck. This may be impossible if Duck is in an external library.

In Python, you just pass your Person to in_the_forest and it works. Because it turns out in_the_forest doesn't need a Duck, it just needs a "duck-like" object, and in this case Person is sufficiently duck-like.

game though, needs a different definition of "duck-like", which is slightly stronger. Here, John Smith is out of luck.

Now, it's true that Java would have caught this error at compile time and Python won't. That can be viewed as a disadvantage. The pro-dynamic-typing counter argument is to say that any substantial body of code you write will always contain bugs that no compiler can catch (and to be honest, Java isn't even a particularly good example of a compiler with strong static checks to catch lots of bugs). So you need to test your code to find those bugs. And if you're testing for those bugs, you will trivially find bugs where you passed a Person to a function that needs a Duck. Given that, the dynamic-typist says, a language that tempts you into not testing because it finds some of your trivial bugs is actually a bad thing. And on top of that, it prevents you from doing some really useful things, like reusing the in_the_forest function on a Person.

Personally I'm torn in two directions. I really like Python with its flexible dynamic typing. And I really like Haskell and Mercury for their powerful static type systems. I'm not much of a fan of Java or C++; in my opinion they have all of the bad bits of static typing with few of the good bits.

这篇关于鸭子打字和(java)界面概念的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆