Idea
I had this idea for a language feature that I think would be useful, does anyone know of a language that implements something like this?
The idea is that besides inheritance a class can also use something called "imprinting" (for lack of better term). A class can imprint one or several (non-abstract) classes. When a class imprints another class it gets all it's properties and all it's methods. It's like the class storing an instance of the imprinted class and redirecting it's methods/properties to it. A class that imprints another class therefore by definition also implements all it's interfaces and it's abstract class.
So what's the point? Well, inheritance and polymorphism is hard to get right. Often composition gives far more flexibility. Multiple inheritance offers a slew of different problems without much benefits (IMO).
I often write adapter classes (in C#) by implementing some interface and passing along the actual methods/properties to an encapsulated object. The downside to that approach is that if the interface changes the class breaks. You also you have to put in a lot of code that does nothing but pass things along to the encapsulated object.
A classic example is that you have some class that implements IEnumerable or IList and contains an internal class it uses. With this technique things would be much easier
Example (c#)
[imprint List<Person> as peopleList]
public class People : PersonBase
{
public void SomeMethod()
{
DoSomething(this.Count); //Count is from List
}
}
//Now People can be treated as an List<Person>
People people = new People();
foreach(Person person in people)
{
...
}
peopleList is an alias/variablename (of your choice)used internally to alias the instance but can be skipped if not needed. One thing that's useful is to override an imprinted method, that could be achieved with the ordinary override syntax
public override void Add(Person person)
{
DoSomething();
personList.Add(person);
}
note that the above is functional equivalent (and could be rewritten by the compiler) to:
public class People : PersonBase , IList<Person>
{
private List<Person> personList = new List<Person>();
public override void Add(object obj)
{
this.personList.Add(obj)
}
public override int IndexOf(object obj)
{
return personList.IndexOf(obj)
}
//etc etc for each signature in the interface
}
only if IList changes your class will break. IList won't change but an interface that you, someone in your team, or a thirdparty has designed might just change. Also this saves you writing a whole lot of code for some interfaces/abstract classes.
Caveats
There's a couple of gotchas. First we, syntax must be added to call the imprinted classes's constructors from the imprinting class constructor.
Also, what happens if a class imprints two classes which have the same method? In that case the compiler would detect it and force the class to define an override of that method (where you could chose if you wanted to call either imprinted class or both)
So what do you think, would it be useful, any caveats? It seems it would be pretty straightforward to implement something like that in the C# language but I might be missing something :)
Side note - Why is this different from multiple inheritance
Ok, so some people have asked about this. Why is this different from multiple inheritance and why not multiple inheritance. In C# methods are either virtual or not.
Say that we have ClassB who inherits from ClassA. ClassA has the methods MethodA and MethodB. ClassB overrides MethodA but not MethodB.
Now say that MethodB has a call to MethodA. if MethodA is virtual it will call the implementation that ClassB has, if not it will use the base class, ClassA's MethodA and you'll end up wondering why your class doesn't work as it should.
By the terminology so far you might already confused. So what happens if ClassB inherits both from ClassA and another ClassC. I bet both programmers and compilers will be scratching their heads.
The benefit of this approach IMO is that the imprinting classes are totally encapsulated and need not be designed with multiple inheritance in mind. You can basically imprint anything.