【问题标题】:Solve inheritance dependency in a functional approach在函数式方法中解决继承依赖性
【发布时间】:2017-09-30 20:13:38
【问题描述】:

The problem:

继承依赖

  • 类型 A 将类型 B 的值存储在属性中

  • 类型 B 继承自类型 A

我们将考虑一个 UI 控件层次结构,其中每个控件都属于顶级“表单”,而表单本身就是一个控件。

作者通过参数化类解决了这个问题:

[<AbstractClass>]
type Control<'Form>(name) = 
    member this.Name = name

    abstract Form : 'Form

type Form(name) = 
    inherit Control<Form>(name)

    override this.Form = this

type Button(name,form) = 
    inherit Control<Form>(name)

    override this.Form = form

let form = new Form("form")       
let button = new Button("button",form)

但是我怎样才能在函数式方法中重新设计:“我们根本不会使用继承。相反,我们会结合参数化使用组合”?

【问题讨论】:

    标签: .net oop inheritance f# functional-programming


    【解决方案1】:

    这个问题很难回答,因为这个问题的表述本质上是面向对象的。当您说“表单是控件”时,问题的“是”部分暗示了一种 OO 建模世界的方式,您通常不会在函数式编程中使用这种方式。

    严格来说,您的示例代码实际上并没有做任何有用的事情 - 它创建了一堆对象,但不使用它们来呈现任何用户界面或实现任何其他功能。
    当然,我怀疑这就是问题所在。如果我想建模一个包含表单和按钮的非常简单的用户界面,我可能会从以下内容开始:

    type SimpleControl = 
      | Button of string
      | Label of string
    
    type ContainerControl = 
      | Form 
    
    type Control = 
      | Container of ContainerControl * Control list
      | Simple of SimpleControl
    

    这使您可以定义可以包含其他控件和按钮和标签的容器控件(例如表单),它们是简单的控件,不能包含其他元素。但这只是一个示例 - 根据您实际想要构建的用户界面类型以及您想要对它们做什么,您可以不同地定义类型。

    简而言之,函数式编程通常需要不同的思维方式,而一些在面向对象世界中有意义的问题在函数式世界中却没有意义。

    【讨论】:

    • 在示例中,有一个字符串Name 属性可用于所有控件类型。所以SimpleControlContainerControl 都应该包含Name 项目。另外,可以在你的代码中解释use composition in conjunction with parameterization吗?
    • 所以 FP 意义上的世界建模本质上是将类型与“或”结合起来?
    • @ftor 我认为用“或”(又名有区别的联合)和“和”(又名记录)来建模世界是一个非常强大的功能技巧。有时,函数/接口也很有用,但如果我倾向于尽可能多地坚持“或”/“和”:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多