I am playing a bit with F# interfaces, by creating a simple data access class.
The interface is:
type IUserAccess =
abstract member GetUsers : (dbSchema.ServiceTypes.Users -> bool) -> dbSchema.ServiceTypes.Users seq
abstract member GetAllUsers : unit -> dbSchema.ServiceTypes.Users seq
In the class, I am calling the methods in this way:
type UserAccess() =
let db = dbSchema.GetDataContext()
interface IUserAccess with
member this.GetUsers cond =
let query = query {
for row in db.Users do
select row }
query |> Seq.where cond
member this.GetAllUsers () =
(this:>IUserAccess).GetUsers (fun _ -> true)
What I'm a bit concerned with is the way I am calling GetAllUsers
function, specifically with part (this:>IUserAccess)
. What is the simplest way of calling methods that are implemented within the same interface?
One simple option I can think of is creating GetUsers
method directly within UserAccess()
class and then calling it from the interface implementation of both GetUsers
and GetAllUsers
, but that means a new private method implemented, which I would like to avoid. Is there another option?
I think the solution by @vcsjones is probably the best option if you want to avoid defining a separate method directly inside the class. That said, declaring a separate method is actually not that ugly. You can use local definition using let
binding (which is automatically compiled as a private method) and I think it makes the code look quite nice:
type UserAccess() =
let db = dbSchema.GetDataContext()
let getUsers cond =
let query = query {
for row in db.Users do
select row }
query |> Seq.where cond
interface IUserAccess with
member this.GetUsers cond = getUsers cond
member this.GetAllUsers () = getUsers (fun _ -> true)
I generally quite like this style, because it separates all the private implementation from the part of the definition where you're defining the public exposed API.
F# always implements interfaces explicitly, so your options are pretty much as you stated, but you can avoid redundant casting by introducing a let binding:
type IUserAccess =
interface
abstract member GetUsers : (obj -> bool) -> unit
abstract member GetAllUsers : unit -> unit
end
type Foo() as self =
let userAccess = self :> IUserAccess
interface IUserAccess with
member this.GetUsers(q : (obj -> bool)) : unit =
()
member this.GetAllUsers() =
userAccess.GetUsers(fun _ -> true)
I just simplified your interface and object so I could get something compiling real quick.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With