March 14, 2007

Implementation Classes Again

I’ve been thinking more about traits and implementation classes in OOP.
I put together a quick program in Nemerle to demonstrate the ideas I’m playing with.

I defined a class that implements System.ComponentModel.IEditableObject. It takes a “user” object as a parameter and implements a simple stack based state saver. BeginEdit copies all the fields of the user, pushing them onto the stack. CancelEdit can then restore state by popping the stack and setting the fields back to those saved values. EndEdit simply pops the stack leaving the current values in place.

    class EditableObject[T] : IEditableObject
        private _states : Stack[Dictionary[FieldInfo, object]] = Stack()
        private _user : T

        // We only take the reflection performance hit once per type T.
        private static _fields : array[FieldInfo]
        static this()
            _fields = typeof(T).GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)

        public this(user : T)
            _user = user

        public BeginEdit() : void
            _states.Push(CopyState())

        public EndEdit() : void
            if (_states.Count > 0)
                _ = _states.Pop() // Discard top of stack
            else
                throw InvalidOperationException()

        public CancelEdit() : void
            if (_states.Count > 0)
                RestoreState(_states.Pop())
            else
                throw InvalidOperationException()

        private CopyState() : Dictionary[FieldInfo, object]
            def dictionary = Dictionary()
            foreach (f in _fields)
                dictionary[f] = f.GetValue(_user)
            dictionary

        private RestoreState(previous : Dictionary[FieldInfo, object]) : void
            foreach (f in _fields)
                f.SetValue(_user, previous[f])

I now want to use this “implementation” class in many different classes. I do not want to inherit from this class directly. Trying to create an abstract base class purely to stuff lots of different implementation details together is just plain ugly too.
So I used the Nemerle ProxyPublicMembers macro.

    class Person : IEditableObject
        [ProxyPublicMembers] _editable : EditableObject[Person] = EditableObject(this)

        [Accessor(flags=WantSetter)] mutable _firstName : string
        [Accessor(flags=WantSetter)] mutable _surname : string

        public this(firstName : string, surname : string)
            _firstName = firstName
            _surname = surname

        public override ToString() : string
            $"$FirstName $Surname"

With the single line:
[ProxyPublicMembers] _editable : EditableObject[Person] = EditableObject(this)
the three public methods BeginEdit, CancelEdit, EndEdit are inserted into Person and they simply call the respective methods on the _editable instance field.

A simple test of the code is:

    static class Program
        static Main() : void
            def p1 = Person("Andrew", "Davey")
            Console.WriteLine(p1)

            p1.BeginEdit()
            p1.FirstName = "Foo" 
            Console.WriteLine(p1)
            p1.CancelEdit()
            Console.WriteLine(p1)

            p1.BeginEdit()
            p1.Surname = "Smith" 
            p1.EndEdit()
            Console.WriteLine(p1)

Outputting:

Andrew Davey
Foo Davey
Andrew Davey
Andrew Smith

One of the advantages of this implementation class approach is the ability to store both instance and static state. The EditableObject only takes the reflection performance hit to get a type’s fields once. The user class never has to know about this state at all.

It would also be possible to enable a form of “overriding” by the user class. Perhaps it needs a special way to save and restore state. We just need a way to tell the implementation class to call the user to do something, rather than doing it itself. Delegates could be passed to the implementation class upon construction. Or perhaps a more declarative approach could be taken by marking “override” methods in a user class with an attribute.

[OverrideImplementation(EditableObject)] private CopyState() : Dictionary[FieldInfo, object]
  // do stuff here

We would just require some macro trickery to get this working I reckon.

As it stands the standard ProxyPublicMethods macro in Nemerle enables an excellent approach to modelling problems in clean OO style. I think an additional macro to tidy up the syntax would make things even nicer.

class Person
  uses EditableObject for IEditableObject

Maybe?


- No comments Not publicly viewable


Add a comment

You are not allowed to comment on this entry as it has restricted commenting permissions.

Trackbacks

  1. Overriding implementation class members

    On the way home I thought of a way to override implementation class members in the user class. class User use SomeImpl for IFooBar [OverrideImpl(IFooBar)] private SomeMethod() : void // specialized code... class SomeImpl : IFooBar public virtual SomeMethod…

    codeMonkey.Weblog(); - 14 Mar 2007, 15:11

Google Ads

Search this blog

Most recent comments

  • I scratched my eye while i was holding some kind of plastic packaging.. Anyways the corner of the pl… by Ercan on this entry
  • About a year ago my contacts that i was wearing, i guess were fautly, because shortly after they wer… by Jon on this entry
  • I got shower gel in my eye 4 and a half days ago, and becasue i rubbed my eyes a lot, i have scratch… by Chris on this entry
  • This website may help http://www.webmd.com/eye–health/tc/Eye–Injuries–Home–Treatment by S on this entry
  • I somehow got dirt, or debris in my eye. The terrible pain sent me in a tailspin. I was afraid of sa… by Bobbi on this entry

Tags

March 2007

Mo Tu We Th Fr Sa Su
Feb |  Today  | Apr
         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   

Galleries

Blog archive

Loading…
Not signed in
Sign in

Powered by BlogBuilder
© MMXIV