Inheritance ';基数';值只能用于直接调用重写成员的基本实现
为什么我不能在这里调用Inheritance ';基数';值只能用于直接调用重写成员的基本实现,inheritance,f#,overriding,base,derived,Inheritance,F#,Overriding,Base,Derived,为什么我不能在这里调用f的base实现: type Base = abstract f : int -> int -> int default this.f (x : int) (y : int) : int = x + y type Derived = inherit Base override this.f (x : int) (y : int) : int = base.f -x -y 调用base.f会引发以下编译器错误: error
f
的base
实现:
type Base =
abstract f : int -> int -> int
default this.f (x : int) (y : int) : int = x + y
type Derived =
inherit Base
override this.f (x : int) (y : int) : int = base.f -x -y
调用base.f
会引发以下编译器错误:
error FS0419: 'base' values may only be used to make direct calls to the base implementations of overridden members
如果我将
f
更改为接受单个参数,则它将编译。大概这与curried参数和tupled参数有关,但是上面的代码在我看来很好。您关于curried参数的假设是正确的。以下代码编译并正常运行:
type Base () =
abstract f : int * int -> int
default this.f (x : int,y : int) : int = x + y
type Derived () =
inherit Base()
override this.f (x : int,y : int) : int =
base.f(-x,-y)
注意:我使用了元组参数。这个原因可能是因为在curried参数中,它将函数分解为多个函数(每个函数取一个参数)我认为问题在于
base
不能通过闭包捕获-必须直接进行调用。但是,重写curried函数会自动创建闭包,因为只有第一个参数会立即应用。因此,尽管看起来您确实在使用base
值来直接调用被重写成员的基本实现,但实际上您在闭包中使用base
值,这是非法的
不幸的是,我认为没有任何好的方法来解决这个问题。一般来说,如果可能的话,你应该避免使用咖喱会员,但这里有一个选择:
type Base =
abstract f : int -> (int -> int)
default this.f (x : int) = fun y -> x + y
type Derived =
inherit Base
override this.f x =
let fn = base.f -x
fun y -> fn -y
@kvb在他的分析中是正确的,但是如果你真的想覆盖一个curried方法,你可以。但语法相当冗长:
type Base =
abstract f : int -> (int -> int)
default this.f (x : int) = fun (y : int) -> x + y
type Derived =
inherit Base
override this.f (x : int) =
let baseCall = base.f -x
fun (y : int) -> baseCall -y
另见:(没有结论)。对我来说,这看起来像是一个编译器错误。我需要一些时间来理解你的答案,但既然你不是说这是一个编译器错误,那么我觉得逻辑上的结论是,既然我所尝试的基本上是惯用的,语言在这方面有缺陷。@jon-有这样一个误导性的错误信息可能是一个编译器错误。此外,没有基本限制阻止基成员从闭包中调用,尽管这不是一个需要解决的小问题。然而,我认为您的代码本质上不是惯用的。在模块中使用curried let绑定函数是惯用的,但使用curried成员并不惯用,正是因为这样的问题。就我个人而言,我不会用F#这样漂亮的函数式语言进行OO编程。如果你真的想做继承、基类等事情,那么就用C语言来做,因为在F语言中,OO神经元会觉得奇怪。F#首先是功能性的,让我们用它来实现only@Ankur:F#被吹捧为一种多范式语言,旨在支持OO和FP风格的编程。Curried成员通常是OOP语用学和FP语用学之间阻抗不匹配的地方之一。(混合F#和C#时会出现很多问题。)混合OOP和FP时,您必须同时设计两种范式,而不是两种范式中的任何一种。令人恼火,但随着使用,它确实变得更加自动化。