Explicit Interface Methods Implementation

In MC++, I can do the following: -

MC++ Sample:
__gc __interface ICloneablePerson
{
Person* Clone();
};


public __abstract __gc class Person : public ICloneablePerson
{
private:
String* _name;

protected:
Person()
:_name(String::Empty)
{
}

Person(String* name)
:_name(name)
{
}

Person(Person* source)
:_name(source->_name)
{
}

public:
__property String* get_Name()
{
return _name;
}
};



public __gc class Student: public Person
{
private:
String* _id;
public:
Student(void)
:Person()
{
_id = String::Empty;
}

Student(String* name)
:Person(name)
{
_id = String::Empty;
}

Student(Student* source)
:Person(source)
{
this->_id = source->_id;
}

Student* Clone()
{
return new Student(this);
}

Person* ICloneablePerson::Clone()
{
return Clone();
}
};



public __gc class Test
{
public:
void static Start()
{
Person* person1 = new Student("David");
Student* person2 = new Student("Anthony");
Person* person3 = person1->Clone();
Student* person4 = person2->Clone();
}
};


However in C# .Net 2.0, I can't do that without explicitly casting.

C# Sample:
interface ICloneablePerson
{
Person Clone();
};

public abstract class Person:ICloneablePerson
{
string _name;

protected Person()
{
_name = string.Empty;
}

protected Person(string name)
{
_name = name;
}

protected Person(Person source)
{
_name = source._name;
}

public abstract Person Clone();
}

public class Student:Person, ICloneablePerson
{
string _id;

public Student()
:base()
{
_id = string.Empty;
}

public Student(string name)
: base(name)
{
_id = string.Empty;
}

public Student(Student source)
:base(source)
{
_id = source._id;
}

public override Person Clone()
{
return new Student(this);
}

Person ICloneablePerson.Clone()
{
return Clone();
}
}

public class Test
{
public static void Start()
{
Person person1 = new Student("David");
Student person2 = new Student("Anthony");
Person person3 = person1.Clone();
Student person4 = person2.Clone() as Student;
}
}

Is there a way to do the same like MC++ without an explicit casting.

Thank you.





Answer this question

Explicit Interface Methods Implementation

  • Dmytro Kryvko

    A better question is what is the goal Student is of type person....hence you can access the properties of type person.

    If one wants a generic reference, try creating another interface which supersedes both person and student and return that instead.


  • William Bartholomew

    aahkam wrote:
    This works well, but must ensure all its child class explicitly implement the interface.


    Sounds like the advice I gave....

    OmegaMan wrote:
    If one wants a generic reference, try creating another interface which supersedes both person and student and return that instead.


  • Lars E.Nes

    Hi

    How about this:

    interface ICloneablePerson
    {
    Person Clone ();
    }

    class Person : ICloneablePerson
    {
    private string _name = String.Empty;
    public Person ( string name )
    {
    _name = name;
    }
    private Person ( Person person ) : this(person.Name)
    {
    }
    public string Name
    {
    get
    {
    return _name;
    }
    }
    Person ICloneablePerson.Clone ()
    {
    return this.Clone();
    }
    public Person Clone ()
    {
    return new Person(this.Name);
    }
    public override string ToString ()
    {
    return "Person: " + _name;
    }
    }

    class Student : Person, ICloneablePerson
    {
    public Student ( string _id ) : base(_id)
    {
    }
    Person ICloneablePerson.Clone ()
    {
    return Clone();
    }
    public new Student Clone ()
    {
    return new Student(this.Name);
    }
    public override string ToString ()
    {
    return "Student: " + Name;
    }
    }

    Now you can do this:

    Person person1 = new Student("David");
    Student person2 = new Student("Anthony");
    Person person3 = person1.Clone();
    Student person4 = person2.Clone() as Student;

    This is OK, too:

    ICloneablePerson person5 = person2.Clone(); // person5 is Student Type

    But this may raise some problem:

    ICloneablePerson person6 = person1.Clone(); // person6 is Person Type

    Yours Markku


  • Duckocide

    After some testing, I found my own solution. This works well, but must ensure all its child class explicitly implement the interface.

    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace SelfPractice.EIMI
    {
    interface ICloneablePerson
    {
    Person Clone();
    };

    public abstract class Person:ICloneablePerson
    {
    string _name;

    protected Person()
    {
    _name = string.Empty;
    }

    protected Person(string name)
    {
    _name = name;
    }

    protected Person(Person source)
    {
    _name = source._name;
    }

    public Person Clone()
    {
    return ((ICloneablePerson)this).Clone();
    }
    }

    public class Student:Person, ICloneablePerson
    {
    string _id;

    public Student()
    :base()
    {
    _id = string.Empty;
    }

    public Student(string name)
    : base(name)
    {
    _id = string.Empty;
    }

    public Student(Student source)
    :base(source)
    {
    _id = source._id;
    }

    public new Student Clone()
    {
    return new Student(this);
    }

    Person ICloneablePerson.Clone()
    {
    return Clone();
    }
    }

    public class Test
    {
    public static void Start()
    {
    Person person1 = new Student("David");
    Student person2 = new Student("Anthony");
    Person person3 = person1.Clone();
    Student person4 = person2.Clone();
    }
    }
    }



  • z-one


    Now you can do this:

    Person person1 = new Student("David");
    Student person2 = new Student("Anthony");
    Person person3 = person1.Clone();
    Student person4 = person2.Clone() as Student;

    This is OK, too:

    ICloneablePerson person5 = person2.Clone(); // person5 is Student Type

    But this may raise some problem:

    ICloneablePerson person6 = person1.Clone(); // person6 is Person Type



    It is not that simple.
    Person has to be an abstract base class. Hence you can't instantiate the Person object.
    Person implements an interface defines the "can" Clone() contract which returns the type of Person.
    Student inherits from the Person class, and has to have a Clone() that returns the type of Student for type safety purpose.

    Although, Functions differ only by its return type is not supported by C# and MC++, but MSIL supports it.
    Although MC++ does not support this feature, but thru the use of EIMI (Explicit Interface Methods Implementation) this can still be done easily to offer greater reference polymorphism.

    However in C#, I couldn't use the same trick again.




  • Xfolder

    The goal is to create a truly polymorphic hierarchy.

    Look at the MC++ code, if the student object to be cloned is cast to a Student reference, it returns the cloned object with a Student reference. If the student object to be cloned is cast to a Person reference, it returns the cloned object with a Person reference without having to cast it explicitly.

    I find it difficult to accomplish in C#, but MC++ does it easily.






  • xlthim

    I don't think it is like your suggestion. Don't you see the difference

    If one wants a generic reference, try creating another interface which supersedes both person and student and return that instead.



    Based on the original question (there is already an interface), but you are suggesting creating another Interface (additional) that supersedes both classes.

    However, the answer shown up there has no such additional Interface at all. It just cast this pointer into its Interface it implements at the base class and calls the clone() of that interface.

    If there is no explicit implementation of the clone function at the child class, the whole algorithm is going to turn up like endless recursion.



  • Explicit Interface Methods Implementation