试图理解F#类定义语法

时间:2011-02-11 19:05:37

标签: .net syntax f# constructor

在了解了这门语言最重要的功能之后,我现在正在接近F#课程。好吧,类定义语法不易理解,但现在我可以清楚地了解一些主要概念,但其他概念则不然。

1)我想知道的第一件事就是正确/不正确。我知道可以用两种方式定义类:

  • 隐式课程。这些类只有一个构造函数,在类的第一行中,有必要使用let绑定定义所有内部变量,为它们赋值。
  • 明确的课程。这些类有许多构造函数。它们通过val绑定接受未初始化的值。这些值必须在构造函数中初始化。如果构造函数无法为使用val绑定定义的至少一个私有变量定义值,编译器就会生气。

是对吗???

2)我在理解显式类中构造函数的语法时遇到了问题。 请考虑以下事项:

这是第一个版本:

(* COMPILES :) *)
type MyType =
   val myval: int
   val myother: int
   (* Constructor *)
   new (a: int, b: int) = {
      myval = a;
      myother = b;
   }

这是第二个版本:

(* COMPILES :) *)
type MyType =
   val myval: int
   val myother: int
   (* Constructor *)
   new (a: int, b: int) = {
      myval = a (* No semicolon *)
      myother = b (* No semicolon *)
   }

这是最后一个版本:

(* DOES NOT COMPILE :( *)
type MyType =
   val myval: int
   val myother: int
   (* Constructor *)
   new (a: int, b: int) = 
      myval = a (* Using the normal indent syntax, without {} *)
      myother = b (* Using the normal indent syntax, without {} *)

我不明白为什么前两个版本编译而第三个使用常规缩进语法却没有。 此问题仅在构造函数中发生,因为在成员上我可以使用缩进语法

(* COMPILES :) *)
type MyType =
   val myval: int
   val myother: int
   (* Constructor *)
   new (a: int, b: int) = {
      myval = a (* No semicolon *)
      myother = b (* No semicolon *)
   }
   (* Indentation accepted, no {} to be inserted *)
   member self.mymember =
      let myvar = myval
      myvar + 10

为什么新函数(构造函数)需要{}括号?????我不喜欢它,因为它似乎考虑了序列。此外,我的代码也在{}球拍中,在一条指令和另一条指令之间,没有插入分号时进行编译。 WHY ????

2 个答案:

答案 0 :(得分:3)

你写的(强调我的):

  

隐式课程。这些类只有一个构造函数,并且在类的第一行中,有必要使用let绑定定义所有内部变量,为它们赋值。

实际上并非如此 - 您可以使用隐式语法来定义具有多个构造函数的类。实际上,我认为几乎总是使用隐式类语法是个好主意(因为它使声明更简单)。隐式类有一个主构造函数,它是你隐式得到的 - 这个构造函数应该采用最大数量的参数(但它可以是私有的):

type Foo(a:int, b:int) =
  do printfn "hello"         // additional constructor code
  member x.Multiple = a * b  // some members
  new(x:int) = Foo(x, x)     // additional constructor

要使构造函数为私有,您可以编写

type Foo private (a:int, b:int) =
  ...

然后您可以使用主构造函数作为初始化所有字段的好方法。

答案 1 :(得分:2)

关于2),构造函数的主体不像典型函数的主体 - 它具有受限的句法形式,并且在{ }部分内它只能包含对父构造函数和赋值的调用字段(类似于记录构造)。定义普通成员时,即使您想要(即,在此上下文中大括号不是可选的,也禁止它们),也无法将单个表达式包装在{ }中。