代码之家  ›  专栏  ›  技术社区  ›  James Black

继承类型时获取“值未定义”

  •  3
  • James Black  · 技术社区  · 14 年前

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

    1. 基岛.fs
    2. 创建数据库.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
    

    继承的类型在这里,并且 execNonQuery 未定义。

    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))"
    
    1 回复  |  直到 14 年前
        1
  •  5
  •   Tomas Petricek    14 年前

    在f_中,不能仅通过成员的名称隐式调用继承成员(以及在当前类型中定义的成员)-您需要以某种方式引用类型的实例。在您的情况下,您可以使用 base 关键字。以下方法应该有效:

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

    [编辑] 只有当 createRestaurantTable 是一个 member -不是使用 let (如上例所示)。原因是f编译器不允许caputr 基础 在闭包中,它将上面的示例解释为闭包。您可以将其转换为成员并编写:

    type CreateDatabase() = 
        inherit BaseDAO() 
        private member x.createRestaurantTable conn = 
            x.execNonQuery "..."
    

    [/编辑]

    或者,也可以使用 as self (类似于使用 member self.Foo() = .. 在成员声明中。这还允许您从构造函数调用当前类型的成员:

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

    我更喜欢 基础 关键字(因为引用构造函数中的当前实例会给编译器带来各种麻烦)。