为什么F#中没有受保护的访问修饰符?

Dan*_*iel 39 f#

有没有更好的方法在F#中建模数据以避免需要它?

Tom*_*cek 38

protected修改可以在F#很成问题,因为你经常需要从lambda表达式调用成员.但是,当您这样做时,您不再从类中访问该方法.当使用在C#中声明的受保护成员时,这也会引起混淆(例如参见此SO问题).如果您可以声明protected成员,则以下代码可能会令人惊讶:

type Base() = 
  protected member x.Test(a) = a > 10

type Inherited() = 
  inherit Base()
  member x.Filter(list) =
    list |> List.filter (fun a -> x.Test(a))
Run Code Online (Sandbox Code Playgroud)

这段代码不起作用,因为你是Test从lambda函数调用的(这是一个与当前实例不同的对象Test),所以代码不起作用.我认为这是protected在F#中不支持修饰符的主要原因.

在F#中,您通常使用实现继承(即从基类继承)的频率低于C#,因此您不需要protected经常使用.相反,通常优选使用接口(在面向对象的F#代码中)和高阶函数(在功能代码中).但是,很难说如何避免protected一般的需要(除了避免实现继承).你有一些具体的例子可以激发你的问题吗?

  • 这是事实,但它是编译器的实现工件.没有根本原因,类似F#的.NET语言无法生成嵌套类来容纳闭包并具有预期的语义. (32认同)
  • @Tomas - 我同意你的评论的后半部分:我不记得在使用F#时曾经缺少`protected`成员.至于你的评论的前半部分,我认为这与揭露一个包装受保护成员的公共成员有什么不同.C#的方法对我来说似乎非常直观,而且我没有看到任何抱怨/混淆. (11认同)
  • 正好@Liviu当我在推特上询问这个问题时,我收到的答案是"虽然F#支持面向对象,但却以一种固执的方式这样做".我认为这更接近F#不支持定义受保护成员的真正原因:没有编写大量面向对象代码的人并不认为这很重要.遗憾的是,如果不支持受保护的F#,则不能将其视为.NET中的一等公民. (4认同)
  • 请参阅Eric Lippert撰写的这篇博客文章(http://blogs.msdn.com/ericlippert/archive/2005/11/14/why-are-base-class-calls-from-anonymous-delegates-nonverifiable.aspx)讨论类似的问题如何导致C#编译器先前发出无法验证的代码,尽管代码生成方法已经改变以在C#4中解决这个问题. (2认同)
  • 这是F#家伙对C#伙伴没有任何同情心的地方之一.当然它可以实现,但是在c#中,F#语言达到了某个阶段,即作者(主要贡献者)不想添加任何内容,即使它显然是缺失的.另一个例子:F#中的类型推断很酷,但不完整,你可以实现聪明的黑客攻击,但是你不能简单明了地做到这一点:重载模块操作符或模块函数,使用unicode chars进行自定义操作. (2认同)

kvb*_*kvb 8

至于F#是否能够提供更好的数据建模方式,签名文件允许比internalC#更精细的可见性决策,这通常非常好.请参阅Brian的评论,以获得更多解释.但是,这与支持(或缺乏支持)无关protected.