Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# F中的多构造函数与类继承#_F# - Fatal编程技术网

F# F中的多构造函数与类继承#

F# F中的多构造函数与类继承#,f#,F#,我很难将以下C代码转换为F代码: class-Foo { 公共Foo(){} 公共Foo(字符串名){} } 酒吧类别:富 { 公共条():基(){} 公共栏(字符串名称):基(名称){} 公共字符串名称{get;set;} } 我第一次尝试跟踪,但它报告了错误 类型“Bar”的构造函数必须直接或间接调用其 隐式对象构造函数。使用对隐式对象的调用 构造函数而不是记录表达式 然后,我尝试了以下操作,但它现在在自动属性上报告错误 “成员val”定义仅允许在具有主值的类型中使用 构造器。考虑向类型定

我很难将以下C代码转换为F代码:

class-Foo
{
公共Foo(){}
公共Foo(字符串名){}
}
酒吧类别:富
{
公共条():基(){}
公共栏(字符串名称):基(名称){}
公共字符串名称{get;set;}
}
我第一次尝试跟踪,但它报告了错误

类型“Bar”的构造函数必须直接或间接调用其 隐式对象构造函数。使用对隐式对象的调用 构造函数而不是记录表达式

然后,我尝试了以下操作,但它现在在自动属性上报告错误

“成员val”定义仅允许在具有主值的类型中使用 构造器。考虑向类型定义添加参数“

” 这包括:

type Foo() =
    new(name:string) = Foo()

type Bar(name : string) =
    inherit Foo()
    new() = Bar(null) // or whatever you want as a default.
    member val Name:string = name with get, set
见和

查看反编译,C#将是(删除属性):

公共类栏:Program.Foo{
内部字符串名称@;
公共字符串名{
得到{
返回此.Name@;
}
设置{
this.Name@=值;
}
}
公共栏(字符串名称){
this.Name@=Name;
}
公共栏():此(空){
}
}
公开课Foo{
公共食物({
}
public Foo(字符串名称):this(){
}
}

如果一个类的名称(包括
()
)后面直接有一个参数列表,那么它就有一个主构造函数。使用它,任何
继承
声明都只放在这个主构造函数中,它直接位于类声明之后和任何
成员
声明之前

不清楚您试图实现什么。类
Foo
有一个构造函数接受字符串参数,但却放弃了它。一对(技术上)有效的类似类是:

type Foo(name:string) =
    member f.NameLength = name.Length

type Bar(initialName) = // WARNING: this will not end well
    inherit Foo(initialName)
    member val Name:string = initialName with get, set
但这是不合理的代码。
Foo
将保留初始名称,即使更改了
Bar
中的名称。
Bar.name.Length
返回当前名称的长度,而
Bar.NameLength
返回初始名称的长度

要保留默认构造函数,可以添加
new()=Bar(null)
(或
Foo
中的等效项),但请注意null被视为仅互操作的功能。它不用于面向F的代码;如果可能,请分别使用适当的选项类型或空字符串(取决于字符串是空的还是根本不存在)

此外,F#component设计指南中也不鼓励继承类——这是有充分理由的。虽然用例很少,但这些用例通常涉及一个很小的基类和一个派生类(它是基类的完美超集)。通过将一个类作为另一个类的成员来组合类型要常见得多


我不知道这有多重要,但下面是一个带有默认构造函数的类的示例,以及一个使用它的附加构造函数:

type Text500(text : string) =
    do if text.Length > 500 then
        invalidArg "text" "Text of this type cannot have a length above 500."
    member t.Text = text
    new () = Text500("")
它利用主构造函数来验证输入,并有一个额外的、无参数的构造函数,该构造函数使用空字符串。(我不确定额外的构造函数在实际应用中是否有用。)

如果您希望F#源代码编译成与C#代码完全相同的API,答案如下:

type Foo =
    new() = {}
    new(name:string) = { }

type Bar =
    inherit Foo

    [<DefaultValue>] 
    val mutable private name:string

    new() = { inherit Foo() }
    new(name) = { inherit Foo(name) }

    member x.Name with get() = x.name and set v = x.name <- v
输入Foo=
new()={}
新建(名称:string)={}
铅条=
继承福
[] 
val可变私有名称:字符串
new()={inherit Foo()}
new(name)={inherit Foo(name)}

成员x.Name和get()=x.name和set v=x.name谢谢;但这不再是同一个C代码了,对吗?我理解示例C代码不是真正的代码,但问题是看我们是否可以用F#实现精确的逻辑……如果没有其他好的替代方案来解决这个问题,我会在几天内接受你的答案。它确实不太一样(
Bar.Name
string
taking构造函数中获得一个值),但是–IMO–更有意义(如果
Name
属性位于基类型中,则意义更大)。对于cour5se,其中的一些差异是反汇编的。IL显示了字段的实现细节。在这种情况下,您仍然无法添加以下内容:带有get的member val Name=null,setYes,我监督了这一点。我编辑了Bar类以包含一个Name属性。它不是一个auto属性,但API和语义完全相同在C#案例中是。没有其他方法可以“不折不扣地”复制您的C#示例。同意;这是目前最接近的解决方法。我遇到了以下编译器错误:
没有可用于类型“Foo”的构造函数。
。修复方法是
new()={inherit Foo()}
@DharmaTurtle:很高兴它现在对您有效;仅供参考,您提到的这一行已经存在于答案中。我正在尝试使用WPF,我怀疑这里的空构造函数会有所帮助。
type Text500(text : string) =
    do if text.Length > 500 then
        invalidArg "text" "Text of this type cannot have a length above 500."
    member t.Text = text
    new () = Text500("")
type Foo =
    new() = {}
    new(name:string) = { }

type Bar =
    inherit Foo

    [<DefaultValue>] 
    val mutable private name:string

    new() = { inherit Foo() }
    new(name) = { inherit Foo(name) }

    member x.Name with get() = x.name and set v = x.name <- v