La herencia de implementación modela una relación "IS A KIND OF", mientras que la herencia de interfaz modela una relación "CAN BEHAVE LIKE". No es coincidencia que muchos de los nombres de la interfaz BCL terminen con "-able", que representa la capacidad de hacer algo. Para demostrarlo, la imagen del código siguiente:
class Person
{
public string Name{get;set;}
public void Walk() {/*code elided*/}
}
class Employee : Person
{
public int Id{get;private set;}
}
Es evidente que un empleado "es una especie de" Persona. Todos los empleados son personas, por lo tanto, todos tienen un nombre y pueden caminar(). Por supuesto, hacer Persona o Empleado abstracto, no cambia el hecho de que todos los empleados son personas.
Ahora vamos a ponernos un poco más abstractos y hablar sobre el concepto de ser un vehículo. Lo esencial para que una cosa sea un vehículo es que debe poder moverse y detenerse. Puede incluir dirección y transporte de pasajeros, pero lo mantengo muy abstracto.
Pensemos en algunas cosas que son vehículos. Un automóvil, por supuesto, pero ¿qué tal una persona? Pueden moverse y detenerse (y cuando les doy a mis sobrinos y sobrinas a cuestas también llevo pasajeros). ¿Una silla blanca? Siempre estoy entreteniéndome en la oficina. También soy un entusiasta marinero y uso el viento para acelerar y desacelerar mi vehículo.
No puede modelar este tipo de relación utilizando la herencia de implementación, porque tiene muchas cosas diferentes que "pueden actuar como" un vehículo pero que no necesariamente heredan de la misma clase base.
Un pogostick (con disculpas a los pogo-ers profesionales) ES UN TIPO DE Juguete, pero PUEDE ACTUAR COMO un vehículo. No todos los juguetes son vehículos. Una persona no tiene ninguna relación con un automóvil, aparte del hecho de que PUEDE ACTUAR como vehículo.
interface IVehicle
{
void Move();
void Stop();
}
class Toy{}
class PogoStick : Toy, IVehicle
{
public void Move(){ /* boing boing */}
public void Stop(){ /* fall over */}
}
class Car: IVehicle
{
public void Move(){ /* vroom vroom */}
public void Stop(){ /* <screeeech!> */}
}
class Person : IVehicle
{
public string Name{get;set;}
public void Walk() {/*code elided*/}
void IVehicle.Move() { Walk(); }
void IVehicle.Stop() { /*whatever!*/}
}
class Program
{
static void Main()
{
IVehicle[] vehicles = new IVehicle[3];
vehicles[0] = new PogoStick();
vehicles[1] = new Car();
vehicles[2] = new Employee(); //implements IVehicle because it IS A KIND OF Person
vehicles.ForEach(v => v.Move());
//it's worth pointing out that
vehicles[2].Stop();
//works fine, but
Person p = new Person();
p.Move();
//won't, as I explicitly implemented the interface, meaning I can only get at the
//methods via a reference to the interface, not to the implementing class.
}
}
Para usar un ejemplo de .NET, ¿qué tiene en común una cadena en común con una lista? No mucho, excepto que pueda "foreach" ambos:
class Demo
{
static void Main()
{
string s = "Hello!";
List<Employee> payroll = new List<Employee>();
for each (var item in s)
{
Console.WriteLine(item);
}
for each (var item in payroll)
{
Console.WriteLine(item);
}
}
La clase base común para la cadena y la lista es objeto, pero no todos los objetos son "foreach-poder", por lo que no tiene que estar pasando algo más. A saber, que ambos implementan la interfaz IEnumerable (¡hay que -able!)
¿Por qué no elegir un ejemplo donde hay herencia múltiple, por ej. un administrador admite 'ITest' y' ISerializable' y 'ICloneable', etc. ¡Entonces sin duda responderá a su propia pregunta! –
So Interfaz utilizada básicamente para implementar Herencia múltiple. ningún otro uso. – Shikha
Esto es casi duplicado de http://stackoverflow.com/questions/2151959/using-interface-variables - las respuestas allí pueden responder a su pregunta (vea también los comentarios a la respuesta aceptada). – itowlson