简体   繁体   English

从抽象类继承抽象扩展方法

[英]Abstract extension method inheritance from abstract class

I'm trying to achieve the following, not sure yet that it is at all possible: (Behind the scene is a CarFactory I tried to do - implementing the Factory design pattern) 我正在尝试实现以下目标,尚不确定是否有可能:(在幕后是我尝试做的CarFactory-实现Factory设计模式)

I have a abstract class "Car" with solid properties that are shared between all cars and I have features like "RadioDisc", "FuelInjection" which not all cars have. 我有一个抽象类“汽车”,该类具有在所有汽车之间共享的实体属性,并且具有并非所有汽车都具有的诸如“ RadioDisc”,“ FuelInjection”之类的功能。

There could be several types of "RadioDisc" or "FuelInjection". 可能有几种类型的“ RadioDisc”或“ FuelInjection”。

Each of these features follows a certain pattern, has shared properties but the installation process on a car is different. 这些功能中的每一个都遵循特定的模式,具有共享的属性,但是在汽车上的安装过程不同。

I want each feature to make changes to Car based on a method that can do some stuff. 我希望每个功能都基于可以执行某些操作的方法对Car进行更改。

The extension should look something like this: 扩展名应如下所示:

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

Ideally it should do like this, but I have compiler error- 理想情况下,它应该这样做,但是我有编译器错误-

Extension method must be defined in a non-generic static class 扩展方法必须在非通用静态类中定义

Of course I don't want a general static method, I want a method that will have same signature but will do something diffrent to the car on each class that inherit Feature. 当然,我不需要通用的静态方法,我想要一个具有相同签名,但会对继承Feature的每个类的汽车做些不同的事情。

Example for feature is FuelInjection that add Cost to the car, and let's say improve FuelConsumption property on Car. 该功能的示例是FuelInjection,它增加了汽车的成本,并且说要改善Car的FuelConsumption属性。

Abstract Feature class: 抽象要素类:

public abstract class Feature
{
    internal float _cost;

    public float Cost
    {
        get
        {
            return _cost;
        }
    }

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

Specific 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.
        }
}

Is that even possible in c#? 在C#中甚至可能吗? Is there a different direction to go maybe? 也许有不同的方向吗?

You can always define an interface(or use your abstract class): 您总是可以定义一个接口(或使用您的抽象类):

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

inherit from it: 继承自:

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

and then make an extension: 然后进行扩展:

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

in case of your abstract class it would be just: 在您的抽象类的情况下将只是:

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

If I understood your problem correctly, you should be looking for decorator pattern. 如果我正确理解了您的问题,则应该寻找装饰器模式。

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

From the site: 从站点:

"Decorator pattern is used to add new functionality to an existing object without changing its structure. Hence Decorator pattern provides an alternative way to inheritance for modifying the behavior of an object." “装饰器模式用于在不更改其结构的情况下向现有对象添加新功能。因此,装饰器模式提供了一种替代的继承方式,用于修改对象的行为。”

Code sample from dotnet-tricks site: 来自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();

 }
}

The compiler message already told you that it's not possible in the way you are trying to do it. 编译器消息已经告诉您,您尝试执行此操作的方式是不可能的。 An extension method must be a static method of a static class. 扩展方法必须静态类的静态方法。

So you can only declare your method as simple abstract/instance methods: 因此,您只能将您的方法声明为简单的抽象/实例方法:

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

But you can create a simple extension with a Feature parameter to almost wrap the call like you wanted: 但是,您可以使用Feature参数创建一个简单的扩展,以几乎像您希望的那样包装呼叫:

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

And us it like 而我们喜欢

myCar.Install(V1);

(assuming that V1 is your instance of FuelInjection ). (假设V1是您的FuelInjection实例)。 There is no need for generics here as all features inherit from Feature . 此处不需要泛型,因为所有功能都继承自Feature

But really, I don't see how this is better than calling V1.Install(car) directly. 但实际上,我看不出这比直接调用V1.Install(car)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM