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