具有相同参数类型的构造函数

时间:2020-03-05 18:44:06  来源:igfitidea点击:

我有一个带有两个构造函数的Person对象,一个构造函数使用int(personId),另一个构造函数使用字符串(logonName)。我想要另一个采用字符串(badgeNumber)的构造函数。我知道无法做到这一点,但似乎是一种常见情况。有解决这个问题的优雅方法吗?我想这将适用于任何重载方法。代码:

public class Person
{
    public Person() {}

    public Person(int personId)
    {
        this.Load(personId);
    }

    public Person(string logonName)
    {
        this.Load(logonName);
    }

    public Person(string badgeNumber)
    {
        //load logic here...
    }

...等等。

解决方案

回答

我们可能会考虑使用自定义类型。

例如,创建LogonName和BadgeNumber类。

然后函数声明看起来像...

public Person(LogonName ln)
{
    this.Load(ln.ToString());
}

public Person(BadgeNumber bn)
{
    //load logic here...
}

这样的解决方案可能为我们提供了一个很好的位置,可以保留控制这些字符串的格式和用法的业务逻辑。

回答

不。

我们可能会考虑一个标志字段(可读性枚举),然后让构造函数使用htat来确定意思。

回答

我唯一想处理我们想要做的事情就是必须使用params,一种描述参数类型(带有LogonName,BadgeNumer等的枚举),第二种是param值。

回答

那行不通。我们可能会考虑制作一个称为BadgeNumber的类,该类包装一个字符串,以避免这种歧义。

回答

我们也许可以改用工厂方法?

public static Person fromId(int id) {
    Person p = new Person();
    p.Load(id);
    return p;
}
public static Person fromLogonName(string logonName) {
    Person p = new Person();
    p.Load(logonName);
    return p;
}
public static Person fromBadgeNumber(string badgeNumber) {
    Person p = new Person();
    // load logic
    return p;
}
private Person() {}

回答

我们不能有两个具有相同签名的不同构造函数/方法,否则,编译器将如何确定要运行的方法。

正如Zack所说,我会考虑创建一个"选项"类,在其中我们可以实际传递自定义类型中包含的参数。这意味着我们可以传递尽可能多的参数,并使用选项进行操作,只是要小心不要创建试图做所有事情的整体方法。

或者,或者投票支持工厂模式。

回答

我们可以使用静态工厂方法:

public static Person fromLogon(String logon) { return new Person(logon, null); }
public static Person fromBadge(String badge) { return new Person(null, badge); }

回答

我们可以切换到工厂样式模式。

public class Person {

  private Person() {}

  public static PersonFromID(int personId)
  {
    Person p = new Person().
    person.Load(personID);

    return p;
    this.Load(personId);
  }

  public static PersonFromID(string name)
  {
    Person p = new Person().
    person.LoadFromName(name);

    return p;
  }

  ...
}

或者,如建议的那样,使用自定义类型。我们也可以使用泛型来破解某些东西,但出于可读性考虑,我不建议我们这样做。

回答

正如已经建议的那样,在这种情况下,自定义类型是可行的方法。

回答

怎么样 ...

public Person(int personId)
{
    this.Load(personId);
}

public Person(string logonName)
{
    this.Load(logonName);
}

public Person(Object badgeNumber)
{
    //load logic here...
}

回答

我们可以想到四个选项,其中三个已经被其他人命名:

  • 按照其他几个人的建议,走工厂路线。这样做的一个缺点是我们不能通过重载获得一致的命名(否则我们将遇到相同的问题),因此从表面上看不太干净。另一个较大的缺点是,它排除了直接在堆栈上分配的可能性。如果采用这种方法,则所有内容都将分配在堆上。
  • 自定义对象包装器。这是一种很好的方法,如果我们是从头开始的话,我会建议我们这样做。如果我们有很多使用(例如)徽章作为字符串的代码,那么重写代码可能会使该选项不可行。
  • 在方法中添加一个枚举,指定如何处理字符串。这可行,但是要求我们重写所有现有调用以包括新的枚举(尽管我们可以根据需要提供默认值以避免其中的某些情况)。
  • 添加一个未使用的伪参数来区分两个重载。例如在方法上添加一个" bool"。标准库在几个地方都采用了这种方法,例如std :: nothrowoperator new的伪参数。这种方法的缺点是丑陋且无法扩展。

如果我们已有大量的现有代码,建议我们添加枚举(可能具有默认值)或者添加哑参数。两者都不漂亮,但两者都很容易改装。

如果我们是从头开始或者仅有少量代码,则建议我们使用自定义对象包装器。

如果代码大量使用原始的badge/logonName字符串,但不大量使用Person类,则可以使用factory方法。

回答

如果使用的是C3.0,则可以使用对象初始化程序:

public Person()
{
}

public string Logon { get; set; }
public string Badge { get; set; }

我们将这样调用构造函数:

var p1 = new Person { Logon = "Steve" };
var p2 = new Person { Badge = "123" };