Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否可以从基类构造函数创建派生类?_C#_Inheritance_Polymorphism - Fatal编程技术网

C# 是否可以从基类构造函数创建派生类?

C# 是否可以从基类构造函数创建派生类?,c#,inheritance,polymorphism,C#,Inheritance,Polymorphism,我有三门课,动物,猫和狗 // calling code var x = new Animal("Rex"); // would like this to return a dog type var x = new Animal("Mittens"); // would like this to return a cat type if(x.GetType() == typeof(Dog)) { x.Bark(); } else { x.Meow(); } class Anima

我有三门课,动物,猫和狗

// calling code
var x = new Animal("Rex"); // would like this to return a dog type
var x = new Animal("Mittens"); // would like this to return a cat type

if(x.GetType() == typeof(Dog))
{
   x.Bark();
}
else
{
  x.Meow();
}


class Animal
{
   public Animal(string name)
   {
      // check against some list of dog names ... find rex
      // return Animal of type Dog.

      // if not...

      // check against some list of cat names ... find mittens
      // return Animal of type Cat.
   }
}

这有可能吗?如果没有,我能做些类似的事情吗?

您要找的是“虚拟构造函数”(C#中不可能)或工厂模式

class Animal
{
   // Factory method
   public static Animal Create(string name)
   {
      Animal animal = null;
      ...  // some logic based on 'name'
          animal = new Zebra();

      return animal;
   }
}

Factory方法也可以放在另一个(Factory)类中。这提供了更好的解耦等。

不。基本上正确的解决方法是使用静态方法,该方法可以创建正确类型的实例:

var x = Animal.ForName("Rex");
var x = Animal.ForName("Mittens");

...

public abstract class Animal
{
    public static Animal ForName(string name)
    {
        if (dogNames.Contains(name))
        {
            return new Dog(name);
        }
        else
        {
            return new Cat(name);
        }
    }
}
或者这可能是
AnimalFactory
类型(或其他类型)中的实例方法。这将是一种更具扩展性的方法——例如,工厂可以实现一个接口,并且可以注入到创建实例所需的类中。不过,这确实取决于上下文——有时这种方法有些过头了


基本上,
newfoo(…)
调用总是准确地创建
Foo
的实例。然而,使用返回类型
Foo
声明的静态方法可以返回对与
Foo
兼容的任何类型的引用。不,我认为这是不可能的

您可以创建一个静态类,该类有一个基于名称返回动物的方法,例如

static Animal CreateAnimal(string name)
{
    if(catList.Contains(name))
        return new Cat(name");
    else if(dogList.Contains(name))
        return new Dog(name);

    return null;
}

其他答案表明,您需要使用工厂模式,但我想给您一个更“实际”的示例,说明如何使用工厂模式。我做的和你们做的完全一样,但我和你们一起工作。当我看到
X
时,我需要创建类
Rectangle
的实例,当我看到
a
时,我需要创建类
Text
的实例

(我写了这篇文章,因此我确信我所做的一些事情可以改进)

DrawableItemBase

public abstract class DrawableItemBase : Epl2CommandBase, IDrawableCommand
{
    protected DrawableItemBase()
    {
        Location = new Point();
    }
    protected DrawableItemBase(Point location)
    {
        Location = location;
    }
    protected DrawableItemBase(int x, int y)
    {
        Location = new Point();
        X = x;
        Y = y;
    }
    private Point _Location;
    [XmlIgnore]
    public virtual Point Location
    {
        get { return _Location; }
        set { _Location = value; }
    }

    [XmlIgnore]
    public int X
    {
        get { return _Location.X; }
        set { _Location.X = value; }
    }
    [XmlIgnore]
    public int Y
    {
        get { return _Location.Y; }
        set { _Location.Y = value; }
    }

    abstract public void Paint(Graphics g, Image buffer);
}
public abstract partial class Epl2CommandBase : IEpl2Command
{
    protected Epl2CommandBase() { }

    public virtual byte[] GenerateByteCommand()
    {
        return Encoding.ASCII.GetBytes(CommandString + '\n');
    }
    public abstract string CommandString { get; set; }
}
Epl2CommandBase

public abstract class DrawableItemBase : Epl2CommandBase, IDrawableCommand
{
    protected DrawableItemBase()
    {
        Location = new Point();
    }
    protected DrawableItemBase(Point location)
    {
        Location = location;
    }
    protected DrawableItemBase(int x, int y)
    {
        Location = new Point();
        X = x;
        Y = y;
    }
    private Point _Location;
    [XmlIgnore]
    public virtual Point Location
    {
        get { return _Location; }
        set { _Location = value; }
    }

    [XmlIgnore]
    public int X
    {
        get { return _Location.X; }
        set { _Location.X = value; }
    }
    [XmlIgnore]
    public int Y
    {
        get { return _Location.Y; }
        set { _Location.Y = value; }
    }

    abstract public void Paint(Graphics g, Image buffer);
}
public abstract partial class Epl2CommandBase : IEpl2Command
{
    protected Epl2CommandBase() { }

    public virtual byte[] GenerateByteCommand()
    {
        return Encoding.ASCII.GetBytes(CommandString + '\n');
    }
    public abstract string CommandString { get; set; }
}
各种接口:

public interface IEpl2GeneralFactoryProduct
{
    string GetFactoryKey();
}
public interface IEpl2Command
{
    string CommandString { get; set; }
}

public interface IDrawableCommand : IEpl2Command
{
    void Paint(System.Drawing.Graphics g, System.Drawing.Image buffer);
}

事实上没有限制你自己。。。您的基类需要知道它的子类,这不是很有用。