【问题标题】:C#: Multiple Inheritance with Non-Abstract Computed PropertiesC#:具有非抽象计算属性的多重继承
【发布时间】:2011-03-04 20:24:11
【问题描述】:

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

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 
{
  //
}

但是一个类不能从两个抽象类继承。所以我需要使用接口,但是使用接口我不能有方法体。然后,我必须在多个类中定义完全相同的函数,以使用接口实现这些简单的布尔属性。

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

是否有一种设计模式通过允许函数体来模仿抽象类,但允许像接口这样的多个继承者?

【问题讨论】:

  • 这与您的问题没有直接关系,而只是几个 cmets:1. 您可能想改用 DateTime?(可为空的 DateTime),然后您可以改用 DeletionDate != nullreturn DeletionDate != default(DateTime)。 2. C# 约定在接口名称前加上“I”,所以你会想要IModifiableIDeletable

标签: c# inheritance abstract-class


【解决方案1】:

这不是多重继承,但想到的是扩展方法。

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

【讨论】:

    【解决方案2】:

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

    当涉及到接口时,这是可能的,因为当您定义多个接口时,您还需要全部实现它们。

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

    【讨论】:

      【解决方案3】:

      我忘记了设计模式的名称,但是有一种模式可以通过将方法/属性调用包装在同一个接口的成员的接口实现周围来实现多个接口:

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

      【讨论】:

        【解决方案4】:

        是的,实际上有几种方法。一些想法:

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

        显然,以上都没有多重继承的所有优点。如果要在 .NET 中实现多重继承,可以使用 C++.NET 或 Eiffel.NET。

        【讨论】:

          【解决方案5】:

          抱歉,在 C# 中不能实现多重继承,这对你来说是个遗憾。您的选择是:

          1. 要么链接你的基类继承,比如 MyClass : MyBaseClass : EvenBasierClass
          2. 或从多个接口继承。并实现所有接口的所有方法。

          它并不漂亮,但您还可以通过检查实例类型来控制属性的可访问性或在类中返回值。

          【讨论】:

            【解决方案6】:

            Modifiable & Deletable 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);
                }
            }
            

            【讨论】:

            • 要是我想到了就好了……
            • @rqdq 我看到您发布了几乎完全相同的 code 解决方案,但是我的答案的第一行是我没有删除它的原因。
            • 我同意接口评论。扩展方法是主观的,我不会使用它们,因为你有能力修改类。当你不能直接修改类时,扩展方法是最好的。
            • 扩展方法破坏了封装,而且您已经从对象本身中删除了计算的属性,从而防止子类覆盖它们的行为。
            【解决方案7】:

            我可能会使用委托来实现这一点。创建 Modifiable 和 Deletable 作为接口,然后创建它们的实现。给出这些实现的Something 类实例。这是可删除的示例:

            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
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2017-02-23
              • 2023-03-05
              • 1970-01-01
              • 2013-04-18
              • 2016-05-08
              • 1970-01-01
              • 1970-01-01
              • 2012-03-04
              相关资源
              最近更新 更多