在C#中具有多个构造函数的抽象类

3

我有一个名为Commandclass,我想将它解析成字符串/从字符串解析,以便将其作为UDP消息发送。基类看起来很简单:

public abstract class Command
{
    public Command() {}
    public abstract override string ToString();
    public abstract void FromString(string str);
}

我从这里派生出像这样的东西

public class NetCommand : Command
{
   public string details;

   public NetCommand() {};
   public override string ToString() {return details;}
   public override void FromString(string str) {details = str; }
}

或者稍微复杂一些,包含 xyz 以及被解析的 doublesMovementCommand : Command.

如何在基础 class 中添加一个构造函数,该构造函数接受一个 string 并使用 FromString 方法? 所有派生类将具有完全相同的代码,看起来像这样:

public Command(string str)
{  
    this.FromString(str);
}

每个class将使用自己的FromString方法从字符串中填充其自己的成员。

但是我对语法感到困惑,需要帮助吗?


public NetCommand(string str): base(str){} - user2140173
这正是我所期望的,尽管我认为在派生类中可以不使用任何代码包含此构造函数,只需确保任何派生类都具有此构造函数。如果您将其添加为解决方案,我将接受它。 - javirs
当然,没问题。我为你添加了一个答案。 - user2140173
5个回答

2

这正是您所需要的,包括对抽象类的更改:

public abstract class Command
{
    public Command() { }
    public Command(string str)
    {
        FromString(str);
    }
    public abstract override string ToString();
    public abstract void FromString(string str);
}
public class NetCommand : Command
{
    public string details;
    public NetCommand() {}
    public NetCommand(string str) : base(str) { }
    public override string ToString() { return details; }
    public override void FromString(string str) { details = str; }
}

如果有人继承了Command类,但没有包含public MyCommand(string str) : base(str) { }`这一行代码,然后你尝试调用它会发生什么呢?看起来这里存在一个弱点:( - javirs
你需要从抽象类中实现Command(string str)方法,如果你不打算在继承Command的类中使用它,那么这是不必要的,因为抽象类不能直接创建。不,你不能强制要求从抽象类继承的类实现所有构造函数,语言并不要求这样做。 - ipavlu
您无法直接调用不存在的构造函数。反射会有不同的情况,但是那样会失败。您只是想要完成或不完成某些事情 :)。 - ipavlu

0
我理解您的意思是,您想要一个创建子类对象的基类构造函数。但是这是不可能的。
您可以在基类上创建一个静态工厂方法,根据给定的字符串创建具体的对象,例如:
public abstract class Command
{
    public Command() {}
    public abstract override string ToString();
    public abstract void FromString(string str);

    public static Command FromString(string str){
        Command command;
        if(/*string indicates it is a NetCommand*/){
            command = new NetCommand();
            command.FromString(str);
        }
    }
}

或者更好的方式是:command = new NetCommand(str),其中NetCommand(string str)是一个私有/受保护的构造函数。 - CompuChip
@CompuChip 是的,那可能是更好的设计。 - Domysee
1
@javirs你如何计划反序列化它,如果你无法知道确切的类型? - Domysee
大家好,这里有一个设计缺陷。静态的FromString返回的是Command,但实际上应该是NetCommand。但作者说,会有多个类继承自抽象类Command。这意味着要么每个实现都需要有多个版本的静态FromString,要么就需要另一种机制,比如public static TRslt FromString<TRslt>(string str) where TRslt : Command。 - ipavlu
1
@ipavlu,你说得对,我们确实不知道这是否是情况。幸运的是,这不是唯一的答案,OP可以选择最适合他解决方案的答案。然而,当序列化某些内容并通过网络发送时,通常会出现这种情况。 - Domysee
显示剩余3条评论

0

拥有一个后备字段,用于存储通过构造函数传递的值,然后再定义两个虚方法来设置和返回该值。请注意,在下面的实现中,NetCommand 只能使用非无参构造函数进行实例化。

public abstract class Command
    {
        private string _details;

        protected Command()
        {
        }

        protected Command(string details)
        {
            _details = details;
        }

        public new virtual string ToString()
        {
            return _details;
        }

        public virtual void FromString(string details)
        {
            _details = details;
        }
    }

    public class NetCommand : Command
    {
        public NetCommand(string str) : base(str)
        {
        }
    }

0
我建议采用这种实现方式(尽可能将代码放入基类中,以便更轻松地创建进一步的类)。
public abstract class Command {
  protected Command(): this(null) {
  }

  protected Command(String details) {
    Details = details;
  }

  // I'd rather convert it into property
  public String Details {
    get;
    set; // may be "private set" will be better here
  }  

  public override string ToString() {
    return Details;
  }

  // TODO: think on delete or redesign this method:
  // Redundant: Details provide all the functional required
  // Bad name: "FromString" usually means create/return
  // instance by given details
  //  public static Command FromString(string details)  
  public virtual void FromString(String details) {
    Details = details;
  }
}

...

public class NetCommand: Command {
  public NetCommand(string details) : base(details) {
  }
}

0
扩展Domysee的答案,使用通用工厂方法,您可以执行以下操作:
public abstract class Command
{
    protected Command() {}
    public abstract override string ToString();
    protected abstract void FromString(string str);

    public static T FromString<T>(string str) where T: Command, new()
    {
         var command = new T();
         command.FromString(str);
         return command;
    }
}

现在,只要派生的 Command 类有一个默认构造函数,您就可以使用 Command.FromString 创建它的实例,如下所示: var command = Command.FromString<NetCommand>("command string");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接