Inheritance 获得;“未定义值”;继承类型时

Inheritance 获得;“未定义值”;继承类型时,inheritance,f#,Inheritance,F#,我看不出我做错了什么,因为文件的顺序是正确的。在这种情况下,它是: BaseDAO.fs CreateDatabase.fs 它们在同一个名称空间中,但即使我将它们放在不同的模块中,并且在CreateDatabase中打开模块时也会出现相同的错误 错误是: Error 1 The value or constructor 'execNonQuery' is not defined 我正在尝试继承BaseDAO并使用一个对多个文件通用的成员,我不明白为什么会出现上述错误 namesp

我看不出我做错了什么,因为文件的顺序是正确的。在这种情况下,它是:

  • BaseDAO.fs
  • CreateDatabase.fs
  • 它们在同一个名称空间中,但即使我将它们放在不同的模块中,并且在
    CreateDatabase
    中打开模块时也会出现相同的错误

    错误是:

    Error   1   The value or constructor 'execNonQuery' is not defined  
    
    我正在尝试继承
    BaseDAO
    并使用一个对多个文件通用的成员,我不明白为什么会出现上述错误

    namespace RestaurantServiceDAO
    
    open MySql.Data.MySqlClient
    
    type BaseDAO() =
        let connString = @"Server=localhost;Database=mysql;Uid=root;Pwd=$$$$;"
        let conn = new  MySqlConnection(connString)
    
        member self.execNonQuery(sqlStr) =
            conn.Open()
            let comm = new MySqlCommand(sqlStr, conn, CommandTimeout = 10)
            comm.ExecuteNonQuery |> ignore
            comm.Dispose |> ignore
    
    此处是继承的类型,未定义
    execonquery

    namespace RestaurantServiceDAO
    
    open MySql.Data.MySqlClient
    
    type CreateDatabase() =
        inherit BaseDAO()
    
        let createRestaurantTable conn =
            execNonQuery "CREATE TABLE restaurant(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), cur_timestamp TIMESTAMP(8))"
    
    在F#中,继承的成员(以及在当前类型中定义的成员)不能仅通过成员的名称隐式调用-您需要以某种方式引用该类型的实例。在您的情况下,可以使用
    base
    关键字。以下方面应起作用:

    type CreateDatabase() = 
        inherit BaseDAO() 
        let createRestaurantTable conn = 
            base.execNonQuery "..."
    
    [EDIT]只有当
    createRestaurantTable
    成员时,此功能才有效,而不是使用
    let
    声明的函数(如上面的示例所示)。原因是F#编译器不允许在闭包中使用caputring
    base
    ,它将上面的示例解释为闭包。您可以将其转换为成员并写入:

    type CreateDatabase() = 
        inherit BaseDAO() 
        private member x.createRestaurantTable conn = 
            x.execNonQuery "..."
    
    [/EDIT]

    或者,您也可以使用
    将该类型的当前实例命名为self
    (这类似于在成员声明中使用
    成员self.Foo()=..
    指定实例。这还允许您从构造函数调用当前类型的成员:

    type CreateDatabase() as self = 
        inherit BaseDAO() 
        let createRestaurantTable conn = 
            self.execNonQuery "..."
    

    如果可能的话,我更喜欢
    base
    关键字(因为在构造函数中引用当前实例会给编译器带来各种各样的麻烦).

    我不能使用base.execonquery,因为它抱怨闭包,但我确实将它们变成了成员,这解决了我的问题。谢谢you@James:你说得对-
    base
    不能在
    let
    绑定函数中使用。这有点不公平-添加
    作为self
    可能是另一种选择(它生成一些运行时检查,以确保初始化是正确的,并且在类完全初始化之前不使用
    self
    ,但这应该不是什么大问题)。