Simulating Multiple Inheritance by Delegation
page 4 of 5
by Joseph Chahine
Feedback
Average Rating: 
Views (Total / Last 10 Days): 27876/ 76

How to use it?

As per the definition above, the receiving object in our example is an instance of the MyCustomCollection class, so we should derive it from MarshalByRefObject. To make it act as it is also inheriting from System.Collections.ArrayList, we will create a class called MyCustomCollectionSlave that inherits from System.Collections.ArrayList.

MyCustomCollectionSlave will act as an object delegate to MyCustomCollection (MyCustomCollectionSlave was not called MyCustomCollectionDelegate to avoid confusion with the .NET System.Delegate type).

Now we need to inject (or "inherit") the behaviors of MyCustomCollectionSlave into MyCustomCollection. This why we define a field within MyCustomCollection called InnerList of type MyCustomCollectionSlave and we write dumb entries for all methods of MyCustomCollectionSlave in MyCustomCollection. These methods will only be responsible for forwarding calls to the MyCustomCollectionSlave corresponding methods. The following listings make things easier to understand.

Listing 1

[C#]

//This class plays the role of a delegate
internal class MyCustomCollectionSlave : System.Collections.ArrayList
{
    #region "Methods"
 
        public object GetSomething() {
            //Write some code here
        }
 
    #endregion
}
public class MyCustomCollection : System.MarshalByRefObject
{
    
#region "Fields"
 
    private MyCustomCollectionSlave _InnerList;
 
#endregion
 
#region "Properties"
 
    //Through this property, all delegation is done.
    private MyCustomCollectionSlave InnerList {
        get {
                return this._InnerList;
            }
    }
 
    //The properties below help delegating ArrayList's built-in properties.

     public int Count {
        get {
            return this.InnerList.Count;
        }
    }
 
    public bool IsSynchronized {
        get {
            return this.InnerList.IsSynchronized;
        }
    }
 
    public object SyncRoot {
        get {
            return this.InnerList.SyncRoot;
        }
    }
 
    public bool IsFixedSize {
        get {
            return this.InnerList.IsFixedSize;
        }
    }
     
    public bool IsReadOnly {
        get {
            return this.InnerList.IsReadOnly;
        }
    }
 
    public object this[int index] {
        get {
            return this.InnerList[index];
        }
        set {
             this.InnerList[index] = value;
        }
    }
 
#endregion
 
 
#region "Constructors"
 
    public MyCustomCollection() {
        this._InnerList = new MyCustomCollectionSlave();
    }
 
#endregion
 
#region "Methods"
 
    //This method simply forwards calls to the GetSomething() method in InnerList
    public object GetSomething() {
       return this.InnerList.GetSomething();
    }
 
    public void CopyTo(System.Array array, int index)  {
        this.InnerList.CopyTo(array, index);
    }
 
    public System.Collections.IEnumerator GetEnumerator() {  
        return this.InnerList.GetEnumerator();
    }
 
    public int Add(object value) {
        return this.InnerList.Add(value);
    }
 
    public void Clear() {
        this.InnerList.Clear();
    }
 
    public bool Contains(object value) {
        return this.InnerList.Contains(value);
    }
 
    public int IndexOf(object value) { 
        return this.InnerList.IndexOf(value);
    }
 
    public void Insert(int index, object value) {
        this.InnerList.Insert(index, value);
    }
 
    public void Remove(object value)  {
        this.InnerList.Remove(value);
    }
 
    public void RemoveAt(int index) {
        this.InnerList.RemoveAt(index);
    }
 
    public object[] ToArray() {
        return ((System.Collections.ArrayList)InnerList).ToArray();
    }
 
    public object[] ToArray(System.Type type) {
        return (object[])(((System.Collections.ArrayList)InnerList).ToArray(type));
    }
 
#endregion
 
}

[VB]

'This class plays the role of a delegate
Friend Class MyCustomCollectionSlave
    Inherits System.Collections.ArrayList

 #Region "Methods"
 
    Public Function GetSomething() As Object 
        'Write some code here
    End Function

 #End Region

 End Class
 
Public Class MyCustomCollection
    Inherits MarshalByRefObject
    
#Region "Fields"
 
    Private _InnerList As MyCustomCollectionSlave
 
#End Region
 
#Region "Properties"
 
    'Through this property, all delegation is done.
    Private ReadOnly Property InnerList() As MyCustomCollectionSlave
        Get
            Return Me._InnerList
        End Get
    End Property
 
    'The properties below help delegating ArrayList's built-in properties.
 
    Public ReadOnly Property Count() As Integer
        Get
            Return Me.InnerList.Count
        End Get
    End Property
 
    Public ReadOnly Property IsSynchronized() As Boolean
        Get
            Return Me.InnerList.IsSynchronized
        End Get
    End Property
 
    Public ReadOnly Property SyncRoot() As Object 
        Get
            Return Me.InnerList.SyncRoot
        End Get
    End Property
 
    Public ReadOnly Property IsFixedSize() As Boolean 
        Get
            Return Me.InnerList.IsFixedSize
        End Get
    End Property
 
    Public ReadOnly Property IsReadOnly() As Boolean 
        Get
            Return Me.InnerList.IsReadOnly
        End Get
    End Property
 
    Default Public Property Item(ByVal index As IntegerAs Object 
        Get
            Return Me.InnerList.Item(index)
        End Get
        Set(ByVal value As Object)
            Me.InnerList.Item(index) = value
        End Set
    End Property
 
#End Region
 
 
#Region "Constructors"
 
    Public Sub New()
        Me._InnerList = New MyCustomCollectionBase
    End Sub
 
#End Region
 
#Region "Methods"
 
 
    //This method simply forwards calls to the GetSomething() method in InnerList
    Public Function GetSomething() As Object
        Return Me.InnerList.GetSomething()
    End Function
 
    'The methods below help delegating ArrayList's built-in methods.

     Public Sub CopyTo(ByVal array As System.Array, ByVal index As Integer) 
        Me.InnerList.CopyTo(array, index)
    End Sub
 
    Public Function GetEnumerator() As System.Collections.IEnumerator 
        Return Me.InnerList.GetEnumerator
    End Function
 
    Public Function Add(ByVal value As ObjectAs Integer 
        Return Me.InnerList.Add(value)
    End Function
 
    Public Sub Clear()
        Me.InnerList.Clear()
    End Sub
 
    Public Function Contains(ByVal value As Object) As Boolean 
        Return Me.InnerList.Contains(value)
    End Function
 
    Public Function IndexOf(ByVal value As Object) As Integer 
        Return Me.InnerList.IndexOf(value)
    End Function
 
    Public Sub Insert(ByVal index As IntegerByVal value As Object) 
        Me.InnerList.Insert(index, value)
    End Sub
 
    Public Sub Remove(ByVal value As Object) 
        Me.InnerList.Remove(value)
    End Sub
 
    Public Sub RemoveAt(ByVal index As Integer)
        Me.InnerList.RemoveAt(index)
    End Sub
 
    Public Function ToArray() As Object()
        Return CType(Me.InnerList, ArrayList).ToArray()
    End Function
 
    Public Function ToArray(ByVal type As System.Type) As Object() 
        Return CType(Me.InnerList, ArrayList).ToArray(type)
    End Function
 
#End Region
 
End Class

The example above is a simple one. A good practice would be to create a generic base class the same way we created MyCustomCollection, call it for example MyCustomCollectionBase(Of T). You can use delegation to simulate multiple inheritance within this class.

Note that we can delegate the behaviors of more than one class; this allows simulating inheritance not only from a couple of classes as in our example above, but also from any number of classes.

Then we can derive new classes from MyCustomCollectionBase(Of T). This has the same effect as deriving them from the classes inherited and delegated by MyCustomCollectionBase. For example, we can create a class called MyOrderCollection that is derived from MyCustomCollectionBase (Of OrderInfo).


View Entire Article

User Comments

No comments posted yet.






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2021 ASPAlliance.com  |  Page Processed at 2021-11-29 9:54:31 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search