繁体   English   中英

如何使用 Inheritance 摘要 Class?

[英]How to use Inheritance Abstract Class?

我需要一些有关 Inheritance class 示例的帮助(摘要)。 我不能使用我的 function ToCSV() 因为我返回了 BananaPart 的列表,而 C# 想要一个 FruitPart 的列表。 怎么可能解决这个问题?

using System;
using System.Collections.Generic;
                    
public class Program
{
    public static void Main()
    {
        FruitFactory fruitFactory = new FruitFactory();
        Fruit myFruit = fruitFactory.Create("banana");
        
        myFruit.FruitPart.ForEach(f => Console.WriteLine(f.ToString()));
    }
}

public class FruitFactory {
    public Fruit Create(string fruitType) { 
        switch(fruitType) {
            case "banana":
                return new Banana();
                break;
            default:
                throw new Exception("undefined fruitType");
        }   
    }
}

public abstract class Fruit {
    protected string _name;
    protected List<FruitPart> _fruitPart;
    
    public Fruit() {
        this._name = "A fruit";
    }
    
    public string Name { get { return this._name; } }
    public List<FruitPart> FruitPart { get { return this._fruitPart; } }
}

public abstract class FruitPart { }

public class Banana : Fruit {
    public Banana() : base() {
        this._name = "banana";
        this._fruitPart = ToCSV();
    }
    
    public List<BananaPart> ToCSV(){
        return new List<BananaPart> { new BananaPart(5, "10"), new BananaPart(10, "20"), new BananaPart(20, "40") };
    }
}

public class BananaPart : FruitPart {
    private int _seed;
    private string _dimensionPart;
    
    public BananaPart (
        int seed,
        string dimensionPart
    ) {
        this._seed = seed;
        this._dimensionPart = dimensionPart;
    } 
}

我很高兴能更多地了解它! 先感谢您 !

您的代码未编译的原因是因为List<T>不是协变的。 为了编译您的代码,您需要使用具有协变类型参数的IEnumerable<T>更改List<T> 所以变化是:

public abstract class Fruit {
    protected string _name;
    protected IEnumerable<FruitPart> _fruitPart;

    public Fruit() {
      this._name = "A fruit";
    }

    public string Name { get { return this._name; } }
    public IEnumerable<FruitPart> FruitPart { get { return this._fruitPart; } }
}

您可以在此处了解有关协方差的更多信息: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/covariance-contravariance/

简而言之,协方差可以让您根据其他两种类型的赋值兼容性来推断两种类型的赋值兼容性。 由于我们可以将BananaPart分配给FruitPart ,因此我们可以推断IEnumerable<BananaPart>可以分配给IEnumerable<FruitPart>

您的 model 有问题。 假设我有一个香蕉,它有一个水果部分的列表。 现在我可以调用myBananana.FruitParts.Add(new ApplePart()) ,因为香蕉只由香蕉部分组成,所以这是行不通的。

为避免这种情况,您需要对返回的内容进行更多限制。 您可以使用IEnumerable<Fruitpart>而不是使用List<FruitPart> FruitPart> 。 这避免了这个问题,因为您不能向IEnumerable添加任何内容。

如果您正在学习,我还建议您从接口而不是抽象类开始。 后者有时称为“实现继承”,即用于在两个派生类之间共享代码。 这有时很有用,但在大多数情况下,最好将此共享代码放在第三个 class 中,有时称为“组合优于继承”。

使用接口,您的水果可能会像这样:

public interface IFruit
{
    string Name { get; }
    IEnumerable<IFruitPart> FruitPart { get; }
}
public class Banana : IFruit
{
    public Banana() : base() => FruitPart = ToCSV();
    public static List<BananaPart> ToCSV() => new List<BananaPart> { new BananaPart(5, "10"), new BananaPart(10, "20"), new BananaPart(20, "40") };
    public string Name { get; } = "Banana";
    public IEnumerable<IFruitPart> FruitPart { get; }
}
public interface IFruitPart { }
public class BananaPart : IFruitPart
{
    public int Seed { get; }
    public string DimensionPart { get; }
    public BananaPart(int seed, string dimensionPart) => (Seed, DimensionPart) = (seed, dimensionPart);
}

请注意,与抽象的 class 案例相比,您不需要更多的接口变体代码。

您不能安全地将List<Child>转换为List<Parent> ,因为它会让您将Apple添加到List<Banana>

您可以改为创建List<FuitPart>

    public List<FruitPart> ToCSV()
    {
        return new List<FruitPart> { 
            new BananaPart(5, "10"), 
            new BananaPart(10, "20"), 
            new BananaPart(20, "40") };
    }

由于List<BananaPart>不继承List<FruitPart>你不能那样做。

我建议您制作一些包装类,例如FruitedDetailsBananaDetails来继承它。 这样,您可以封装您正在使用的类的具体细节,并且在打包列表时不必处理各种对象转换。

暂无
暂无

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

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