我的问题涉及如何在F#中以功能方式处理继承。为了稍微描述一下,我举一个简单的例子。假设我们想要建立一个由各种动物组成的世界。每种动物都与其他种类(例如姓名,大小等)共享一些属性。此外,每种类型可能具有其他类型,其他人不共享(例如,儿童的数量与狗和猫相关,但是对于蜘蛛不相关)。此外,可能存在与每种动物类型相关联的方法或功能,其对于两种动物类型可以相同或不同,即,存在可能对于特定种类而言过度的默认实施方式。每种动物都可能有仅为此类定义的方法。
现在,在OOP世界中,这可能会导致抽象类具有公共属性和抽象方法,后面是为每种动物类型派生的类。 我不确定如何在F#中功能性地指定域模型。这里: Which to use , abstract class or interface in F#?声称“惯用F#代码使用与C#不同的扩展点(例如将函数/接口作为参数),因此您不需要抽象类”。
如果这是应该采用的方式,是否可以提供一些基本的例子呢?
至于我对此的进一步思考,我认为属性应该封装在某个结构中。那么,F#中这方面的大多数惯用结构都是记录。这是否意味着存在父记录,该记录应包括在对应于特定“子”的其他记录中,即组成而不是继承。然而,在我看来这是一种既不惯用也不特别优雅的解决方法。
我认为如何在F#中建模继承的首选方法是有区别的联合。但是,这并没有解决共享属性和方法的问题。
在我看来,类似于上面提到的模型非常频繁,因为它隐含在大多数企业应用程序中。因此,是否有任何建议如何以功能方式处理(例如上述链接建议的方式或任何其他建议)?或者我们是否应该说这不是一个可以使用功能方法轻松建模的领域?
谢谢。
答案 0 :(得分:9)
您对该示例的描述已经预先假定了面向对象的编程模型。您正在以面向对象的术语描述问题,例如覆盖和为某些类型的动物定义的方法。这使得很难为您提供合理的替代功能表示,因为您的问题已经在答案中假定了面向对象的概念。
首先,当它们有意义时,在F#中使用面向对象的结构是完全没问题的(你的问题中的例子只是一个玩具样本,所以这可能是也可能不是这样)。关键的想法是F#更喜欢组合而不是继承,因此您可能会尝试避免继承(这会导致复杂的对象层次结构),而是从不同方面组成动物。
其次,如果您以不同的方式解释您的问题,那么使用受歧视的联合可能会有完美的功能表示。例如:
type MammalKind = Cat | Dog
type MammalInfo = { Legs : int; Children : int }
type Animal =
| Mammal of MammalKind * MammalInfo
| Spider of (...)
这个想法是构造类型,以便不同种类的动物(你可以以不同的方式处理)有自己的类型。例如,你可以编写一个函数,它接受MammalInfo
并执行一些只对狗和猫有意义的计算(但不适用于蜘蛛)。但正如我前面提到的,你对问题的描述本质上是面向对象的,所以很难看出如何做到这一点。