7 people like it.

Private Implementation Inheritance without boilerplate

How to avoid delegation boilerplate in inhertance heavy OOP code while maintaining proper accessibility like seen here https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/seq.fs#L82 and mentioned in Expert F# 2.0 "Using Partially Implemented Types via Implementation Inheritance " Uses auto-properties that only work with F# 3.0

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
64: 
65: 
(*
How to avoid delegation boilerplate in inhertance heavy OOP code while maintaining proper accessibility
like seen here https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/seq.fs#L82
and mentioned in Expert F# 2.0 "Using Partially Implemented Types via Implementation Inheritance "

Quote from the book:
"If implementation inheritance is used, you should in many cases consider making all implementing 
classes private or hiding all implementing classes behind a signature. For example, the 
Microsoft.FSharp.Collections.Seq module provides many implementations of the seq<'T> interface 
but exposes no implementation inheritance."

Some explanation on why we inheritance should be avoided.
http://sharp-gamedev.blogspot.com/2011/07/why-inheritance-for-code-reuse-should.html

This snippet should remedy the boilerplate mentioned in the following link making it worthwhile.
http://sharp-gamedev.blogspot.com/2011/08/is-it-worth-it.html 

In this example only the base classes have the delegation boilerplate and 
we simulalte a protected Prop setter while keeping the implementations private.

It also demonstates the use of F# 3.0 autoproperties.
*)


type IGameScreen =
    abstract Prop : string
    abstract Update : unit -> string

[<AbstractClass>]
type GameScreenBase() =
    member val Prop = "GameScreen.Prop" with get, set
    abstract Update : unit -> string
    interface IGameScreen with
        member o.Prop = o.Prop
        member o.Update() = o.Update()

let loadingScreen () =
    { new GameScreenBase(Prop = "LoadingScreen.Prop") with
        override o.Update() = "loadingScreen.Update"  } :> IGameScreen
        
type IMenuScreen =
    inherit IGameScreen
    abstract OnCancel : unit -> string

[<AbstractClass>]
type MenuScreenBase() =
    inherit GameScreenBase(Prop = "MenuScreen.Prop")
    abstract OnCancel : unit -> string
    default o.OnCancel() = "MenuScreen.OnCancel"
    interface IMenuScreen with
        member o.OnCancel() = o.OnCancel()

let pauseMenuScreen () =
    { new MenuScreenBase(Prop = "PauseMenuScreen.Prop") with
        //override o.OnCancel() = "pauseMenuScreen.OnCancel"
        override o.Update() = "pauseMenuScreen.Update" } :> IMenuScreen

let l = loadingScreen ()
l.Prop
l.Update()

let p = pauseMenuScreen ()
p.Prop
p.Update()
p.OnCancel()
abstract member IGameScreen.Prop : string

Full name: Script.IGameScreen.Prop
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
abstract member IGameScreen.Update : unit -> string

Full name: Script.IGameScreen.Update
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
Multiple items
type AbstractClassAttribute =
  inherit Attribute
  new : unit -> AbstractClassAttribute

Full name: Microsoft.FSharp.Core.AbstractClassAttribute

--------------------
new : unit -> AbstractClassAttribute
Multiple items
type GameScreenBase =
  interface IGameScreen
  new : unit -> GameScreenBase
  abstract member Update : unit -> string
  member Prop : string
  member Prop : string with set

Full name: Script.GameScreenBase

--------------------
new : unit -> GameScreenBase
val set : elements:seq<'T> -> Set<'T> (requires comparison)

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.set
abstract member GameScreenBase.Update : unit -> string

Full name: Script.GameScreenBase.Update
type IGameScreen =
  interface
    abstract member Update : unit -> string
    abstract member Prop : string
  end

Full name: Script.IGameScreen
val o : GameScreenBase
override GameScreenBase.Prop : string

Full name: Script.GameScreenBase.Prop
property GameScreenBase.Prop: string
override GameScreenBase.Update : unit -> string

Full name: Script.GameScreenBase.Update
abstract member GameScreenBase.Update : unit -> string
val loadingScreen : unit -> IGameScreen

Full name: Script.loadingScreen
type IMenuScreen =
  interface
    inherit IGameScreen
    abstract member OnCancel : unit -> string
  end

Full name: Script.IMenuScreen
abstract member IMenuScreen.OnCancel : unit -> string

Full name: Script.IMenuScreen.OnCancel
Multiple items
type MenuScreenBase =
  inherit GameScreenBase
  interface IMenuScreen
  new : unit -> MenuScreenBase
  abstract member OnCancel : unit -> string
  override OnCancel : unit -> string

Full name: Script.MenuScreenBase

--------------------
new : unit -> MenuScreenBase
abstract member MenuScreenBase.OnCancel : unit -> string

Full name: Script.MenuScreenBase.OnCancel
val o : MenuScreenBase
override MenuScreenBase.OnCancel : unit -> string

Full name: Script.MenuScreenBase.OnCancel
override MenuScreenBase.OnCancel : unit -> string
val pauseMenuScreen : unit -> IMenuScreen

Full name: Script.pauseMenuScreen
val l : IGameScreen

Full name: Script.l
property IGameScreen.Prop: string
abstract member IGameScreen.Update : unit -> string
val p : IMenuScreen

Full name: Script.p
abstract member IMenuScreen.OnCancel : unit -> string
Next Version Raw view Test code New version

More information

Link:http://fssnip.net/aS
Posted:12 years ago
Author:Associat0r
Tags: xna , oop , inheritance , object-oriented programming , object expressions , classes , interface