views:

89

answers:

2

I have a non-disposable class with Open/Close syntax that I'd like to be able to use, so I'm trying to inherit from it, and work the Open into the new and the Close into Dispose.

The second part is ok, but I can't work out how to do the Open:

type DisposableOpenCloseClass(openargs) =
    inherit OpenCloseClass()
    //do this.Open(openargs)  <-- compiler no like
    interface IDisposable
        with member this.Dispose() = this.Close()

(cf. this question which I asked a long time ago, but I can't join the dots to this one)

+9  A: 

Key is as this:

type OpenCloseClass() =
    member this.Open(x) = printfn "opened %d" x
    member this.Close() = printfn "closed"

open System

type DisposableOpenCloseClass(openargs) as this = 
    inherit OpenCloseClass() 
    do this.Open(openargs)
    interface IDisposable 
        with member this.Dispose() = this.Close() 

let f() =
    use docc = new DisposableOpenCloseClass(42)
    printfn "inside"

f()
Brian
+4  A: 

As Brian suggests, you can use the as this clause. However, in F#, it is usually recomended to use subclassing (inheritance) only when there is a really good reason for that (e.g. you need to implement some virtual class and pass it to a .NET library).

If I was implementing your example, I would probably prefer function returning IDisposable using a simple object expression:

let disposableOpenClose(openargs) = 
  let oc = new OpenCloseClass() 
  oc.Open(openargs)  
  { new IDisposable with
      member this.Dispose() = oc.Close() }

let f() =
  use docc = disposableOpenClose(42)
  printfn "inside"

To some point, this is just a personal preference, but I think it is a preferred option, because it is simpler than using inheritance (although I don't have any document to link here :-)). Also, the compiled code may be a bit simpler, because handling as this may require some runtime checks.

Tomas Petricek
Thanks, in my particular case, I needed access to other functions on the 'base' class, so just returning the interface wouldn't be enough.
Benjol