C#:具有非抽象计算属性的多重继承

C#:具有非抽象计算属性的多重继承,c#,inheritance,abstract-class,C#,Inheritance,Abstract Class,我正在创建一系列包含基本属性的接口/抽象类,我希望具有计算属性和多重继承 public abstract class /interface Modifiable { public DateTime ModifiedDate {get; set;} public boo ModifiedToday { get { return DateTime.Now.AddDays(-1).CompareTo(ModifiedDate) >= 0; } } p

我正在创建一系列包含基本属性的接口/抽象类,我希望具有计算属性和多重继承

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) }
   }
}
然后我有一个从这两个接口/抽象类继承的类

public class Something : Modifiable, Deletable 
{
  //
}
但是一个类不能从两个抽象类继承。所以我需要使用接口,但是对于接口,我不能有方法体。然后,我必须在多个类中定义相同的精确函数,以使用接口实现这些简单的bool属性

我也不想让Modifiable从Deletable继承,因为我可能希望某些东西是可修改的,但不是可删除的。这些特定的类不是我的问题,我只是用它们来说明我的问题

是否有一种设计模式通过允许函数体来模拟抽象类,但允许多个继承者(如接口)

没有。C#没有一种机制以这种方式实现多重继承

当涉及到接口时,这是可能的,因为当您定义多个接口时,您还需要实现所有接口


考虑一种不同的设计,可能是使用组合来重用要用于多重继承的类。

对不起,多重继承在C#中是不可能的,这对您来说是个麻烦。你的选择是:

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) }
   }
}
  • 或者将基类继承链接到la MyClass:MyBaseClass:EvenBasierClass
  • 或者从多个接口继承。并实现所有接口的所有方法

  • 这并不漂亮,但您也可以通过检查实例类型来控制类内的属性可访问性或返回值。

    这不是多重继承,而是扩展方法

    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; 
       }
    
    }
    
    这给了被烘焙到类型中的助手方法的“感觉”,但它们恰好在其他地方声明。参加本课程:

    public class MyModifiable :IModifiable
    {
         public ModifiedDate {get; set;}
    }
    
    你可以这样做:

    MyModifiable m = new MyModifiable;
    
    m.ModifiedDate = DateTime.Now;
    
    bool isToday = m.ModifiedToday();
    

    可修改和可删除IMO应该是接口,而不是基类。基类定义类型,而接口描述类型的功能

    就实现代码而言,您始终可以使用扩展方法:

    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);
        }
    }
    

    我可能会利用授权来实现这一点。创建可修改和可删除的接口,然后创建这些接口的实现。给出这些实现的
    Something
    类实例。以下是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
    }
    

    是的,其实有很多方法。一些想法:

    • Deletable
      Modifiable
      等(称为标记接口)使用空接口,然后为它们创建扩展方法。这不像多重继承那样可扩展,但它还有很长的路要走
    • 使用泛型,可能使用相同的标记接口来创建依赖项。这样,您就可以拥有一个基类,其中包含可修改和可删除的所有方法,包括派生类中的抽象方法和重写实现
    • 使用面向方面的编程来获得相同的结果
    • 几乎相同,但您可以使用Castle或类似的库来完成,可能需要借助属性

    显然,以上这些都没有多重继承的所有优点。如果您想在.NET中使用多重继承,可以使用C++ .NET或Effel.net .< /P> < p>我忘记了设计模式名称,但是有一种模式,通过在相同接口的成员接口实现中封装方法/属性调用来实现多个接口:

    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(); }
    }
    

    要是我想到那件事就好了@rqdq我看到您发布了几乎完全相同的代码解决方案,但是我的答案的第一行是我没有删除它的原因。我同意Interfaces的评论。扩展方法是主观的,我不会使用它们,因为您有能力修改类。当您不能直接修改类时,扩展方法是最好的。扩展方法破坏了封装,加上您已从对象本身删除了计算属性,从而防止子类重写其行为。这与您的问题没有直接关系,但只有几条注释:1。您可能想改用
    DateTime?
    (可为空的DateTime),然后可以执行
    DeletionDate!=null
    而不是
    返回删除日期!=默认值(日期时间)
    。2.将“I”放在接口名称之前是一种C#约定,因此您需要
    IModifiable
    IDeletable