2010-05-10 22 views
3

我看不到我做錯了什麼,因爲這些文件的順序是正確的。在這種情況下,它是:在繼承某個類型時獲取「值未定義」

  1. BaseDAO.fs
  2. 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 

繼承的類型在這裏,並且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))" 

回答

5

在F#中,繼承成員(以及成員當前類型定義)不能只由成員的名稱隱式調用 - 你需要參考類型的實例莫名其妙。就你而言,你可以使用base關鍵字。下面應該工作:

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

[編輯]這隻有createRestaurantTablemember - 使用let(如上面的例子)不是一個函數聲明。原因是F#編譯器不允許在閉包中使用caputring base,並且它將上面的示例解釋爲閉包。你可以把它變成構件和寫入:

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 "..." 

我寧願在base關鍵字,如果這可能的(因爲引用構造函數中的當前實例會導致編譯器的各種麻煩)。

+0

我無法使用base.execNonQuery,因爲它抱怨關閉,但我確實將它們變成了成員,並解決了我的問題。謝謝 – 2010-05-10 02:27:20

+0

@James:你說得對 - 'base'不能用在let函數中。這有點不那麼簡單 - 增加'as self'可能是另一種選擇(它會生成一些運行時檢查以確保初始化是正確的,並且在類完全初始化之前不使用'self',但是不應該'不會是個大問題)。 – 2010-05-10 02:41:01