【问题标题】:Abstract extension method inheritance from abstract class从抽象类继承抽象扩展方法
【发布时间】:2016-08-31 15:52:10
【问题描述】:

我正在尝试实现以下目标,但不确定是否完全有可能: (幕后是我尝试做的一个 CarFactory - 实现工厂设计模式)

我有一个抽象类“Car”,它具有在所有汽车之间共享的可靠属性,并且我具有并非所有汽车都有的“RadioDisc”、“FuelInjection”等功能。

可能有几种类型的“RadioDisc”或“FuelInjection”。

这些功能中的每一个都遵循一定的模式,具有共同的属性,但在汽车上的安装过程是不同的。

我希望每个功能都基于可以做一些事情的方法对 Car 进行更改。

扩展应该如下所示:

Car myCar = new Car();  //Car is a class which has solid props & List of Feature class
FuelInjection V1 = new FuelInjection(); 
myCar.Install<FuelInjection>(V1) ; 

理想情况下应该这样做,但是我有编译器错误-

扩展方法必须定义在非泛型静态类中

当然我不想要一个通用的静态方法,我想要一个具有相同签名但会在每个继承 Feature 的类上对汽车执行不同操作的方法。

功能示例是为汽车增加成本的 FuelInjection,比方说改进 Car 上的 FuelConsumption 属性。

抽象要素类:

public abstract class Feature
{
    internal float _cost;

    public float Cost
    {
        get
        {
            return _cost;
        }
    }

    public abstract void Install<T>(this Car car) where T : Feature;
}

具体功能:

  public class FuelInjection : Feature
    {
        public new void Install<T>(this Car car) where T : Feature
        {
            //In iDo some stuff to Car:
            car.price += this._cost; //this suppose to be the Feature instance. 
                                     //I want to add the cost to property "Price" in Car.
        }
}

这在 C# 中是否可行? 可能有不同的方向吗?

【问题讨论】:

  • 什么是MyCar? V1 是什么?很难从伪代码中说出你真正想要实现的目标,但我怀疑你还没有真正理解扩展方法。相反,如果您尝试解释您真正想做的事情,那么提供帮助会更容易。
  • 我认为您不希望它成为一种扩展方法。只需将其设为常规抽象方法并在您的子类中实现即可。我也怀疑你是否需要它是通用的。
  • 不清楚你在问什么。请解释为什么简单地将Install() 方法放在接口声明中是不够的。
  • @JonSkeet 我已经添加了解释。

标签: c# inheritance abstract-class extension-methods


【解决方案1】:

你总是可以定义一个接口(或使用你的抽象类):

public interface IFeature
{
    void Install(Car car);
}

继承它:

public class Feature : IFeature, IComparable
{
    public void Install(Car car) 
    {
         ....
    }
}

然后做一个扩展:

public static class CarExt
{
     public static void InstallFeature(this Car car, IFeature feature) 
     {
         feature.Install(car);  
     }
}

如果是你的抽象类,那就是:

public static class CarExt
{
     public static void InstallFeature(this Car car, Feature feature) 
     {
         feature.Install(car);  
     }
}

【讨论】:

    【解决方案2】:

    如果我正确理解了您的问题,您应该正在寻找装饰器模式。

    参考: http://www.dotnet-tricks.com/Tutorial/designpatterns/VRQT130713-Decorator-Design-Pattern---C

    来自网站:

    “装饰器模式用于在不改变其结构的情况下向现有对象添加新功能。因此,装饰器模式提供了一种替代继承方式来修改对象的行为。”

    来自 dotnet-tricks 网站的代码示例:

    /// <summary>
    /// The 'Component' interface
    /// </summary>
    public interface Vehicle
    {
     string Make { get; }
     string Model { get; }
     double Price { get; }
    }
    
    /// <summary>
    /// The 'ConcreteComponent' class
    /// </summary>
    public class HondaCity : Vehicle
    {
     public string Make
     {
     get { return "HondaCity"; }
     }
    
     public string Model
     {
     get { return "CNG"; }
     }
    
     public double Price
     {
     get { return 1000000; }
     }
    }
    
    /// <summary>
    /// The 'Decorator' abstract class
    /// </summary>
    public abstract class VehicleDecorator : Vehicle
    {
     private Vehicle _vehicle;
    
     public VehicleDecorator(Vehicle vehicle)
     {
     _vehicle = vehicle;
     }
    
     public string Make
     {
     get { return _vehicle.Make; }
     }
    
     public string Model
     {
     get { return _vehicle.Model; }
     }
    
     public double Price
     {
     get { return _vehicle.Price; }
     }
    
    }
    
    /// <summary>
    /// The 'ConcreteDecorator' class
    /// </summary>
    public class SpecialOffer : VehicleDecorator
    {
     public SpecialOffer(Vehicle vehicle) : base(vehicle) { }
    
     public int DiscountPercentage { get; set; }
     public string Offer { get; set; }
    
     public double Price
     {
     get
     {
     double price = base.Price;
     int percentage = 100 - DiscountPercentage;
     return Math.Round((price * percentage) / 100, 2);
     }
     }
    
    }
    
    /// <summary>
    /// Decorator Pattern Demo
    /// </summary>
    class Program
    {
     static void Main(string[] args)
     {
     // Basic vehicle
     HondaCity car = new HondaCity();
    
     Console.WriteLine("Honda City base price are : {0}", car.Price);
    
     // Special offer
     SpecialOffer offer = new SpecialOffer(car);
     offer.DiscountPercentage = 25;
     offer.Offer = "25 % discount";
    
     Console.WriteLine("{1} @ Diwali Special Offer and price are : {0} ", offer.Price, offer.Offer);
    
     Console.ReadKey();
    
     }
    }
    

    【讨论】:

      【解决方案3】:

      编译器消息已经告诉您,您尝试执行此操作的方式是不可能的。扩展方法必须是static类的static方法。

      所以你只能将你的方法声明为简单的抽象/实例方法:

      public abstract class Feature : IComparable
      {
          internal float _cost;
          public abstract void Install(Car car);
      }
      
      public class FuelInjection : Feature
      {
          public override void Install(Car car)
          {
              car.price += this._cost;
          }
      }
      

      但是您可以使用Feature 参数创建一个简单的扩展,几乎可以像您想要的那样包装调用:

      public static class CarExtensions
      {
          public static void Install(this Car car, Feature feature)
          {
              feature.Install(car);
          }
      }
      

      和我们一样

      myCar.Install(V1);
      

      (假设V1 是您的FuelInjection 实例)。 这里不需要泛型,因为所有功能都继承自 Feature。

      但实际上,我看不出这比直接致电V1.Install(car) 更好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-28
        • 1970-01-01
        • 2013-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-24
        • 2012-01-09
        相关资源
        最近更新 更多