注意:在这个问题中我使用的是Python语法和Python术语,但是我要求概念方法,独立于实际编程语言,以确保答案有用为更广泛的受众。
让我们从几个函数开始:
def dog_tell(name, target, what):
print(f"{name} the dog tells {what} to {target}")
def dog_bark(name, target):
print(f"{name} the dog says 'Bark at you, {target}'")
def dog_wag(name, target):
print(f"{name} the dog wags tail at {target}")
def dog_woof(name):
print(f"{name} the dog woofs")
要使用这些函数,第一个参数应该是狗名,所以它会做一些有用的事情:
>>> dog_bark("Jake", "Finn")
Jake the dog says 'Bark at you, Finn'
现在,如果我们对同一只狗使用这些功能很多,将这些功能组合在一起是有意义的,并且只提供一次狗名。至少有两种方法可以做到这一点。
OOP方法是声明Dog类并为其提供名称:
class Dog(object):
def __init__(self, name):
self.name = name
def tell(self, target, what):
print(f"{self.name} the dog tells {what} to {target}")
def bark(self, target):
print(f"{self.name} the dog says 'Bark at you, {target}'")
def wag(self, target):
print(f"{self.name} the dog wags tail at {target}")
def woof(self):
print(f"{self.name} the dog woofs")
>>> jake = Dog("Jake")
>>> jake.bark("Finn")
Jake the dog says 'Bark at you, Finn'
另一种方法是currying:
name = "Jake"
jake_tell = lambda *args: dog_tell(name, *args)
jake_bark = lambda *args: dog_bark(name, *args)
jake_wag = lambda *args: dog_wag(name, *args)
jake_woof = lambda *args: dog_woof(name, *args)
>>> jake_bark("Finn")
Jake the dog says 'Bark at you, Finn'
这两种方法都提供相同的功能 - 它们实质上将一些重复信息附加到所有函数调用。
现在,我们谈到了我的问题。如果Jake经常和Finn谈话怎么办?我想让他们的谈话成为某种实体?我可以通过功能方法轻松做到这一点:
target = "Finn"
jake_tell_finn = lambda *args: dog_tell(name, target, *args)
jake_bark_at_finn = lambda *args: dog_bark(name, target, *args)
jake_wag_at_finn = lambda *args: dog_wag(name, target, *args)
>> jake_bark_at_finn()
Jake the dog says 'Bark at you, Finn'
与实例化相比,这又增加了一步,并将更多信息附加到函数调用中。
但是这种情况下正确的OOP方法是什么?如果我继续将这部分状态信息添加到类方法中,有效地"实例化实例","实例化实例化实例"该怎么办?等等?
为澄清意图,我想到这样的事情:
>>> jake = Dog("Jake")
>>> jake_and_finn = jake.with_buddy("Finn")
>>> jake_and_finn.tell("dirty secrets")
Jake the dog tells dirty secrets to Finn
虽然我知道如何实现这个"",但我的具体实现缺乏可扩展性,抽象性和美感。它伤害了我的美丽感觉,我觉得我对这背后的基本理论缺乏重要的理解。
答案 0 :(得分:0)
如果我理解正确,我认为你在谈论关于graph
的抽象问题。
jake
和finn
是图表中的两个节点,其通信渠道是此图表中的边缘。因此,如果我们将每个“狗”及其通信渠道构建为一个大图,我们可以使用两个类来描述这两个实例。
一个是Dog
作为节点,另一个是Tell
作为边缘。我们将每只狗都实例化为Dog
。 Dog
有一个函数接收一个参数来指定他的伙伴,并返回Tell
的实例作为有向边(根据您的需要确定,它可以是无向的。)
最后,我们使用Tell
的实例进行沟通。
例如:
jake = Dog("jake")
finn = Dog("finn")
jake_and_finn_tell = jake.with_buddy(finn)
# jake_and_finn_tell is an instance of class Tell.
jake_and_finn_tell.tell("dirty secrets")