Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting "value is not defined" while inheriting a type

Tags:

inheritance

f#

I can't see what I am doing wrong, as the files are in the correct order. In this case it is:

  1. BaseDAO.fs
  2. CreateDatabase.fs

They are in the same namespace, but even when I had them in different modules, and opened the module in CreateDatabase the same error.

The error is:

Error   1   The value or constructor 'execNonQuery' is not defined  

I am trying to inherit BaseDAO and use a member that will be common to several files, and I don't see why I get the error above.

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

The type that does inherit is here, and execNonQuery is not defined.

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))"
like image 234
James Black Avatar asked Sep 11 '26 22:09

James Black


1 Answers

In F#, inherited members (as well as members defined in the current type) cannot be called implicitly just by the name of the member - you need to refer to the instance of the type somehow. In your case, you can use the base keyword. The following should work:

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

[EDIT] This works only if createRestaurantTable is a member - not a function declared using let (as in the example above). The reason is that F# compiler doesn't allows caputring base in a closure and it interprets the sample above as a closure. You can turn it into member and write:

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

[/EDIT]

Alternatively, you can also name the current instance of the type using as self (which is similar to specifying the instance using member self.Foo() = .. in member declarations. This also allows you to call members of the current type from the constructor:

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

I'd prefer the base keyword if that's possible (because refering to the current instance in the constructor causes all sorts of headaches to the compiler).

like image 143
Tomas Petricek Avatar answered Sep 13 '26 18:09

Tomas Petricek