gpt4 book ai didi

inheritance - 对象表达式和错误FS0419 : 'base' values may only be used to make direct calls to the base implementations of overridden members

转载 作者:行者123 更新时间:2023-12-02 10:42:12 24 4
gpt4 key购买 nike

标题中的错误是含糊的,但googling it目前在SO上命中了两次,总共击中了五个(建议这是一种罕见的野兽,因此不要期望在这里有太多的访问;)。我希望这个问题在该列表中排第六。

Kvb's answer in this thread提示错误文本具有误导性,如果您从闭包内调用base会引发错误文本,但这并非总是如此,因为它可以工作:

// in a closure, but no FS0419
let myObj = fun foo ->
{ new obj() with override this.ToString() = base.ToString() + foo}

但这失败了(我找到的最简单的方法来举例说明问题):
// not in a closure, but raises FS0419
let myObj =
{ new obj() with override this.ToString() = () |> base.ToString }

我使用的是对象表达式,而不是带有继承的类型声明,并且我尝试通过构建自定义NUnit约束来创建新的FsUnit约束。这是一个简化的版本,显示了我所遇到的问题:
let EndsWithIgnoreWhitespaceContraint expectedResult = 
{ new EndsWithConstraint(expectedResult) with
override __.ApplyTo<'T> (actual: 'T) =
let actual = box actual
if actual :? string then
actual :?> string
|> fun s -> if isNull s then String.Empty else s
|> fun s -> s.Trim()

// error FS0419: 'base' values may only be used to make direct
// calls to the base implementations of overridden members
|> base.ApplyTo
else
exn "String expected .. bla bla..." |> raise }

// make it available to FsUnit's syntax style (overriding existing endWith)
let endWith = EndsWithIgnoreWhitespaceContraint

// using it:
" hello world " |> should endWith "world"

现在,显然不必知道FsUnit即可看到此行为。但是花了我一天零一天的时间才意识到我被骗了,实际上直到我在SO上写下这个问题时我才看到它。

原来这可行:

代替 x |> base.SomeMethod编写 base.SomeMethod x

我觉得这很奇怪。不确定它是错误还是功能。但是由于 |>运算符是内联的(我用其他运算符对其进行了测试),并且它没有创建新的函数(像 >>那样),所以我不明白为什么会出现此错误。

实际上,除了优先级规则等,我看不到 f aa |> f之间的语义差异。那么为什么会出错呢?我违反了什么规则?

最后一个想法,kvb写道“无法从闭包中调用 base… curry 成员自动创建一个闭包”,这表明这是错误的,但是可以编译:
let myObj foo bar = 
{ new obj() with override this.ToString() = base.ToString() + foo + bar}

是否有人确切知道是什么原因导致了该错误?

最佳答案

首先,您误解了“不能在闭包中使用base”的答案。它的意思是指捕获基础本身的闭包-是阻止该工作的捕获,而不是闭包本身。在您的{ new obj }示例中,任何闭包均未捕获base。捕获了整个对象,但是base仅在ToString方法内直接使用。

为了说明,请尝试以下操作:

let myObj = 
{ new obj() with override this.ToString() = (fun() -> base.ToString())()}

该代码不会编译,因为 base被闭包 fun() -> base.ToString()捕获。

其次,将对象方法用作函数不能像人们期望的那样“直接”工作,因为.NET方法的表示方式不同于F#函数。相反,当遇到诸如 let x = obj.M之类的东西时,编译器会将其视为 let x = fun a -> obj.M(a)-即,将其包装在闭包中。

为了说明,请尝试以下操作:
let myObj = 
{ new obj() with
override this.ToString() =
let f = base.ToString // Error here
f()
}

看到这是怎么回事? :-)

当通过管道传递给对象方法时,编译器必须创建该闭包,然后将其传递给管道运算符。为了说明,请尝试以下操作:
let myObj = 
{ new obj() with
override this.ToString() =
() |> base.ToString // Same error
}

关于inheritance - 对象表达式和错误FS0419 : 'base' values may only be used to make direct calls to the base implementations of overridden members,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45107917/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com