编辑代码

  // type 'T stack_of_a() as self =
  type stack_of_a<'T>() =
    let mutable inner_list: 'T list = []
    member self.push x =
      inner_list <- (x :: inner_list)

    member self.pop =
      let result = inner_list.Head
      inner_list <- inner_list.Tail
      result

    member self.peek = inner_list.Head
    member self.size = inner_list.Length

  // F# 不能像 OCaml 那样做到可以推导出 drain_stack 可以操作在 所有有 pop 和 size 方法的对象上!如果定义另一个有pop和size方法的类, 就可以把 drain_stack 应用到相应的对象上。
  // 只能强制接收特定的类型,只允许 drain_stack 接收 'a stack:
  let drain_stack (s: stack_of_a<int> ) =
    while s.size > 0 do
      ignore (s.pop)

  let s = stack_of_a<int> ()
  for i = 1 to 10 do s.push i
  while s.size > 0 do printfn "pop of inner_stack is %d" s.pop

  [<AbstractClass>]
  type widge (name: string) =
    member self.name = name
    abstract repaint: unit -> unit
    // default self.repaint()=() // 除非带有 AbstractClass 属性, 否则 default 不可缺

  // [<AbstractClass>]
  type container (name: string) =
    inherit widge (name)
    let mutable inner_widges: widge list = []
    member self.add w =
      inner_widges <- w::inner_widges
    member self.widges = inner_widges
    override self.repaint() =
      inner_widges |> List.iter (fun w->w.repaint() )
      // 等同于 List.iter (fun w->w.repaint()) inner_widges

  type button_state = Released|Pressed
  type button (name, ?callback) =
    inherit container (name) // 不如 ocaml, 不能用 as super
    let mutable state = Released
    member self.press () =
      state <- Pressed
      match callback with
      |None -> ()
      |Some f -> f()
    member self.release () =
      state <- Released
    override self.repaint () =
      base.repaint() // 调用父类 只能用 base
      printfn "the Button <%s> being repainted, the state is %s"
        name (
          match state with
          |Pressed-> "Pressed"
          |Released-> "Released"
      )

  let btn = button (
              callback = (fun () -> printfn "Ouch!"),
              name = "my button"
          )
  btn.repaint()
  btn.press()
  btn.repaint()
  btn.release()

  type label (name, text) =
    inherit widge(name)
    override self.repaint () =
      printfn "the label <%s> calls %s" name text

  let lbl = label ("Label", "Press me!")
  btn.add (lbl :> widge) // 不加:>转型 编译未报错
  btn.repaint()

  let mutable wl = ([]: widge list)
  wl <- (btn :> widge)::wl

  let lbl2 =
    {new label("Label2", "Press U!") with // 此处 new 不可缺
      member x.repaint() =
        printfn "another label <%s> calls %s" "Label 2" "Press U!"
    } // 对象表达式(Object Expression)
  (*  F#的对象表达式也算是一种匿名类型,但它不同于C# 3.0的匿名类型。
    在F#的对象表达式里,可以实现接口的成员或者重写基类的成员,但不能添加任何新的成员;
    而C# 3.0的匿名类型只允许属性的存在。
  *)
  btn.add (lbl2 :> widge)
  btn.repaint()