【问题标题】:Why doesn't F# support nested classes?为什么 F# 不支持嵌套类?
【发布时间】:2012-01-20 21:51:51
【问题描述】:

F# 不支持嵌套类的原因是技术性、风格性还是任意性?

浏览 Reflector 中的 BCL,嵌套类用于枚举器、DynamicMetaObjects,可能还有其他一些东西。

这激起了我对 F# 没有此功能的好奇心。我知道还有其他方法可以做同样的事情。我主要是好奇。

【问题讨论】:

  • 它确实支持嵌套(静态)类:module X = module Y = let j = 3;;

标签: f#


【解决方案1】:

我想嵌套类不是 .NET 对象模型的核心特性,它只是被删除以节省资源。可能存在一些技术困难(即可见性或递归类型定义),但我认为这不是主要问题。

对于在 C# 中使用嵌套类的许多情况,例如迭代器,您可以很好地使用对象表达式,所以我猜它们在某些方面可以替代嵌套类:

type Collection() =
  member x.GetEnumerator() = 
    let n = ref 0
    { new IEnumerator with
        member x.Current = box n.Value
        member x.MoveNext() = incr n; true
        member x.Reset() = n := 0 }

虽然这与嵌套类非常相似,但它不会编译为嵌套类,并且对象表达式的主体不能访问Collection 的私有成员。我想支持这一点会使表达式的编译变得有点复杂,因为对象表达式可以出现在类上下文之外......

实际上,可以从对象表达式中访问private 成员,尽管代码仍未编译为嵌套类。详情见 cmets。

【讨论】:

  • 一个小的更正:是可以从对象表达式中引用封闭类型的let bindings/private 成员。在我看来,这使它们成为比嵌套类更好的解决方案。
  • @Daniel 你是对的 - 你可以访问私人成员(我的测试中有一个错误)。有趣的是,当你这样做时,你正在访问的成员要么被内联,要么被编译为 internal 以确保访问安全(但 F# 编译器将其视为 private)。
  • @Tomas:实际上,根据 F# 规范,“all 非公共实体的 CLI 编译形式是内部的。” ...这就是为什么不应该给非 F# 客户端 [] 特权...他们会将 F# 程序集中的所有 private 视为 internal!
  • 我想作弊并创建了同名的模块,但是编译器创建了一个静态类,其名称末尾带有Module。我预计它将合并模块并输入单个 class='(
【解决方案2】:

F# 主要基于没有嵌套类的 Caml。

它可能没有被添加,因为它的优先级不是很高。由于您可以声明在模块外部不可见的数据类型,因此允许内部类不会对代码的封装程度产生太大影响。

【讨论】:

  • 很可能不是这样 - 尽管 F# 主要基于 OCaml,但 F# 中使用的对象模型更多地基于 .NET 而不是 OCaml。
  • +1 表示它们是不必要的,因为您可以使用签名文件来隐藏它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多