2011-03-04 28 views
5

Estoy creando una serie de clases Interfaces/Resumen que contienen propiedades básicas y me gustaría tener propiedades calculadas y herencia múltiple.C#: Herencia múltiple con propiedades calculadas no abstractas

public abstract class /interface Modifiable 
{ 
    public DateTime ModifiedDate {get; set;} 

    public boo ModifiedToday 
    { 
    get { return DateTime.Now.AddDays(-1).CompareTo(ModifiedDate) >= 0; } 
    } 

    public bool ModifiedInLastWeek 
    { 
    get { return DateTime.Now.AddDays(-7).CompareTo(ModifiedDate) >= 0; } 
    } 
} 

public abstract class /interface Deletable 
{ 
    public DateTime DeletionDate {get; set;}  

    public bool Deleted 
    { 
    get { return DeletionDate != default(DateTime) } 
    } 
} 

Luego tengo una clase que hereda de estas dos clases Interfaces/Resumen.

public class Something : Modifiable, Deletable 
{ 
    // 
} 

Pero una clase no puede heredar de dos clases abstractas. Entonces necesito usar interfaces, pero con las interfaces no puedo tener cuerpos de métodos. Luego tengo que definir las mismas funciones exactas en múltiples clases para implementar estas propiedades de bool simples usando interfaces.

Tampoco quiero tener heredabilidad modificable de Deletable porque podría querer que algo sea modificable pero no eliminable. Estas clases específicas no son mi problema, simplemente las estoy usando para ilustrar mi problema.

¿Hay un patrón de diseño que imita una clase abstracta al permitir cuerpos de función, pero permite múltiples herederos como una interfaz?

+2

Esto no está directamente relacionada a su pregunta, pero solo un par de comentarios: 1. Tal vez quiera usar un 'DateTime?' (Nitulo fechable) en su lugar, luego puede hacer 'DeletionDate! = null' en lugar de' return DeletionDate! = default (DateTime) '. 2. Es una convención de C# poner "I" antes de los nombres de las interfaces, por lo que querría tener 'IModifiable' y' IDeletable'. –

Respuesta

1

No. C# no tiene un mecanismo para implementar la herencia múltiple de esta manera.

Cuando se trata de interfaces, esto es posible porque cuando defines múltiples interfaces también necesitas implementarlas todas.

Considere un diseño diferente, posiblemente utilizando composición para reutilizar las clases que desea utilizar para la herencia múltiple.

0

Lo sentimos, la herencia múltiple no es posible en C# y eso es un fastidio para usted. Las opciones son:

  1. ya sea para su cadena de herencia de clases de base A la MiClase: MyBaseClass: EvenBasierClass
  2. o heredar de múltiples interfaces. E implemente todos los métodos de todas las interfaces.

No es bonito, pero también puede controlar el acceso a propiedades o devolver valores dentro de sus clases marcando el tipo de instancia.

1

No es una herencia múltiple, pero algo que se me ocurre son los métodos de extensión.

public interface IModifiable 
{ 
    DateTime ModifiedDate {get; set;} 
} 

public static class ModifiableExtensions 
{ 
    public bool ModifiedToday(this IModifiable m) 
    { 
     return DateTime.Now.AddDays(-1).CompareTo(m.ModifiedDate) >= 0; 
    } 

    public bool ModifiedInLastWeek(this IModifiable m) 
    { 
    return DateTime.Now.AddDays(-7).CompareTo(m.ModifiedDate) >= 0; 
    } 

} 

Eso da la "sensación" de métodos de ayuda que se cuecen en el tipo, sino que pasan a ser declarado en otro lugar. Tomar esta clase:

public class MyModifiable :IModifiable 
{ 
    public ModifiedDate {get; set;} 
} 

Y usted puede hacer esto:

MyModifiable m = new MyModifiable; 

m.ModifiedDate = DateTime.Now; 

bool isToday = m.ModifiedToday(); 
+1

-1: consulta mis comentarios a continuación en la publicación de Scrum Master. –

0

modificables & Deletable OMI debería ser el interfaz, no clases base. Una clase base define qué es un tipo, mientras que una interfaz describe lo que hace un tipo.

En cuanto a la implementación del código, siempre se puede utilizar métodos de extensión:

public interface IModifiable 
{ 
    public DateTime ModifiedDate {get; set;} 
} 

public interface IDeletable 
{ 
    public DateTime DeletionDate {get; set;}  
} 


public static class SomeExtentions 
{ 
    public static bool IsModifiedToday(this IModifiable modifiable) 
    { 
     return DateTime.Now.AddDays(-1).CompareTo(modifiable.ModifiedDate) >= 0; 
    } 

    public static bool IsModifiedInLastWeek(this IModifiable modifiable) 
    { 
     return DateTime.Now.AddDays(-7).CompareTo(modifiable.ModifiedDate) >= 0; 
    } 
    public static bool IsDeleted(this IDeletable deletable) 
    { 
     return deletable.DeletionDate != default(DateTime); 
    } 
} 
+0

Si tan solo hubiera pensado en eso ... RQDQ

+0

@rqdq Veo que ha publicado una solución * code * casi exacta, sin embargo, la primera línea de mi respuesta es la razón por la que no la eliminé. –

+0

Estoy de acuerdo con el comentario de Interfaces. Los métodos de extensión son subjetivos, y no los usaría ya que tiene la capacidad de modificar la clase. Los métodos de extensión son mejores cuando no se puede modificar la clase directamente. –

0

que probablemente utilizar la delegación para lograrlo.Cree Modificable y Deletable como interfaces, luego cree implementaciones de esas. Proporcione las instancias de clase Something de estas implementaciones. Aquí hay un ejemplo para Deletable:

public interface Deletable 
{ 
    DateTime DeletionDate{get;set;} 
    bool Deleted{get;} 
} 

public class DeletableImpl : Deletable 
{ 
    public DateTime DeletionDate{get; set;} 
    public bool Deleted{get {return DeletionDate != default(DateTime);}} 
} 
// Do the same thing with Modifiable and ModifiableImpl 

public class Something : Deletable, Modifiable 
{ 
    private Deletable _deletable = new DeletableImpl(); 
    private Modifiable _modifiable = new ModifiableImpl(); 
    public DateTime DeletionDate 
    { 
    get{return _deletable.DeletionDate;} 
    set{_deletable.DeletionDate = value;} 
    } 
    public bool Deleted{get{return _deletable.Deleted;}} 
    public DateTime ModifiedDate { 
    // and so on as above 
} 
1

Sí, hay métodos, varios, en realidad. Unos pocos pensamientos:

  • utilizar una interfaz vacío para Deletable, etc Modifiable (llamadas interfaces de marcador), a continuación, crear métodos de extensión para ellos. Esto no es tan ampliable como la herencia múltiple, pero tiene un largo camino.
  • Use genericity, posiblemente con las mismas interfaces de etiquetado para crear dependencias. De esta forma puede tener una clase base con todos los métodos para tanto modificable y Deletable, incluyendo métodos abstractos y anular la implementación en las clases derivadas
  • programación orientada
  • Uso aspecto para llegar a los mismos resultados
  • casi lo mismo, pero hacerlo por sí solo con Castle o una biblioteca similar, posiblemente con la ayuda de atributos.

Obviamente, ninguna de las anteriores tiene todas las ventajas de la herencia múltiple. Si desea herencia múltiple en .NET, puede usar C++ .NET o Eiffel.NET.

1

me ha olvidado el nombre del patrón de diseño, pero hay un patrón para implementar múltiples interfaces, envolviendo las llamadas de método/de pisos en las implementaciones de interfaz de miembros que son de esa misma interfaz:

interface IDrivable { 
    void Drive(); 
} 

interface IFlyable { 
    void Fly(); 
} 

class Car : IDrivable { 
    public void Drive() { /* Implementation */ } 
} 

class Plane : IFlyable { 
    public void Fly() { /* Implementation */ } 
} 

class MyClass : IDrivable, IFlyable { 
    private IDrivable _car = new Car(); 
    private IFlyable _plane = new Plane(); 

    public void Drive() { _car.Drive(); } 
    public void Fly() { _plane.Fly(); } 
}