3
votes

I have many classes that implement an interface. Whenever I define a class I have to write something like this within the class definition:

interface Model.IModel with

        member this.Assets          = modelArg.Assets
        member this.AuxData         = modelArg.AuxData
        member this.Benchmark       = modelArg.Benchmark
        member this.CalcPeriods     = modelArg.CalcPeriods
        member this.CashTicker      = modelArg.CashTicker
        member this.Description     = modelArg.Description
        member this.FirstValidDate  = modelArg.FirstValidDate
        member this.Name            = modelArg.Name
        member this.ParamData       = modelArg.ParamData
        member this.ParamList       = modelArg.ParamList
        member this.Strategy        = modelArg.Strategy

        member this.CalcStartTime with get() = calcStartTime and
                                       set v = calcStartTime <- v

        member this.Counter with get() = counter and
                                 set v = counter <- v

Is there a way to avoid repeating this for each and every class that derives from the interface IModel? The code is identical in all cases.

1
A base class that implements the interface and the individual implementations inheriting from that base class is the only way I can think of. (I kind of suspect the more interesting part here is the larger context and purpose, because it might well be that an entirely different approach might be more idiomatic F#.) - TeaDrivenDev
Yes, avoiding classes and inheritance where possible is an important goal in F#, but it being a multiparadigm language, there will be cases where using "object programming", as Don Syme, calls it is necessary or simply the better way. But the things you mention are what I meant when I said the larger context would be the interesting thing here, because that might allow for getting to a completely different design decision. That would be a different question, though, I guess, and require seeing a lot more code that you might not be able to share. - TeaDrivenDev
I would not mind sharing the code but it would be to big and cumbersome. I will try to figure out a simple way to show what I am trying to do and put it in another question. - Soldalma
Why do you have to write this in every class? Having a huge list of properties that you need to include everywhere seems like a massive design issue. - TheInnerLight
why can't you just provide a default implementation? - s952163

1 Answers

2
votes

To make the discussion a bit more concrete, and due to the limited space in the comments, something like the below would or would not work for you?

 type ModelArg = {
     Number: int
     Name: string
 }

 type IModel(modelArg: ModelArg) = 
    abstract member Number: int
    abstract member Name: string
    default __.Number = modelArg.Number
    default __.Name = modelArg.Name

type ConcreteModel1(modelArg: ModelArg) =
    inherit IModel(modelArg)

type ConcreteModel2(modelArg: ModelArg) =
    inherit IModel(modelArg)

let modelArg1 = {Number=2; Name ="Joe"}
let modelArg2 = {Number=3; Name = "Jim"}

let getNumberAndName(x: IModel) =
    (x.Number, x.Name)

let model1 = ConcreteModel1(modelArg1)
let model2 = ConcreteModel2(modelArg2)

getNumberAndName(model1)
//val it : int * string = (2, "Joe")
getNumberAndName(model2)
//val it : int * string = (3, "Jim")