Конструкторы с тем же типом аргумента

HashMap может быть именем Java для концепции, но каждый язык программирования имеет какой-то класс Hash<> или Map<>, и что-то эквивалентное должно быть включено в UML, потому что многие модели включают атрибуты контейнера Hash или Map.

Некоторые инструменты поддерживают стереотип <>; если у вас есть это, я бы использовал его, если вы в основном обеспокоены визуальной интуитивностью, - но нельзя сказать, какой именно ключ подразумевается.

Графическое UML-устройство с квалифицированной ассоциацией не является интуитивным, и я подозреваю, что инструменты для преобразования в что-либо разумное в форвардном генерации кода трудно. Я хотел бы избежать этого.

Другой способ сделать это (что я обычно делаю):

  • создать класс Hash с V и K как общий параметры. Чтобы сделать это правильно, K действительно должен быть ограничен классом, например «Ordered», также отсутствующим в UML (мы всегда добавляем это)
  • для каждого использования Hash, например. Hash (будьте осторожны с порядком - сначала я использую значение, второй - ключ), создайте класс UML с именем Hash и исходящее отношение к Hash<>, а затем сопоставьте V и K с фактическими параметрами Thing и String
  • , то в классе, который хочет его использовать, определите свойство, например things, тип которого - тип Hash.

Например, MagicDraw поддерживает это.

Недостатком этого является то, что вы не увидите ссылку ассоциации между классом клиента и типом значения (Thing в моем примере). Положительным моментом является то, что если вы публикуете свои модели в качестве спецификаторов программистов, это то, что мы делаем, программисты видят правильную вещь в таблицах классов, как вы можете видеть в в этом примере - translation_details attribute.

Трудность в выполнении этой основной задачи в UML является лишь одной из многочисленных проблем с UML, и почему большинство разработчиков, с которыми я встречаюсь сегодня, не используют ее, кроме как для изображений на доске или документации.

7
задан toolkit 9 October 2008 в 00:47
поделиться

12 ответов

Вы могли бы рассмотреть использование пользовательских типов.

Например, создайте классы LogonName и BadgeNumber.

Затем Ваши объявления функции похожи...

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

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

Такое решение могло бы дать Вам хорошее место для хранения бизнес-логики, которая управляет форматом и использованием этих строк.

7
ответ дан 6 December 2019 в 05:50
поделиться

У Вас есть четыре опции, о которых я могу думать, три из которых уже назвали другие:

  1. Пойдите путем фабрики, как предложили несколько других здесь. Один недостаток к этому - то, что у Вас не может быть последовательного именования через перегрузку (или иначе у Вас была бы та же проблема), таким образом, это поверхностно менее чисто. Другой, больше, недостаток - то, что он устраняет возможность выделения непосредственно на стеке. Все будет выделено на "куче", если Вы проявите этот подход.

  2. Обертки пользовательского объекта. Это - хороший подход и тот, который я рекомендовал бы, если Вы запускаете с нуля. Если у Вас есть большое использование кода, например, значки как строки, то перезапись кода может сделать это нежизнеспособной опцией.

  3. Добавьте перечисление к методу, указав, как рассматривать строку. Это работает, но требует, чтобы Вы переписали все существующие вызовы для включения нового перечисления (хотя можно обеспечить значение по умолчанию при желании для предотвращения части этого).

  4. Добавьте фиктивный параметр, который не использован для различения эти две перегрузки. например, Гвоздь a bool на метод. Этот подход проявлен стандартной библиотекой в нескольких местах, например. std::nothrow фиктивный параметр для operator new. Недостатки этого подхода - то, что это ужасно и что это не масштабируется.

Если бы у Вас уже есть большая основа существующего кода, я рекомендовал бы любое добавление перечисления (возможно со значением по умолчанию) или добавление фиктивного параметра. Ни один не красив, но оба довольно просты модифицировать.

Если бы Вы запускаете с нуля или только имеете небольшой объем кода, я рекомендовал бы обертки пользовательского объекта.

Методы фабрики были бы опцией, если у Вас есть код, который в большой степени использует сырые данные badge/logonName строки, но в большой степени не использует Person класс.

2
ответ дан 6 December 2019 в 05:50
поделиться

Вы могли, возможно, использовать методы фабрики вместо этого?

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() {}
18
ответ дан 6 December 2019 в 05:50
поделиться

Нет.

Вы могли бы рассмотреть поле признака (перечисление для удобочитаемости) и затем сделать, чтобы конструктор использовал htat для определения то, что Вы имели в виду.

1
ответ дан 6 December 2019 в 05:50
поделиться

При использовании C# 3.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" };
2
ответ дан 6 December 2019 в 05:50
поделиться

Это не будет работать. Вы могли бы рассмотреть создание класса под названием BadgeNumber, который переносит строку для предотвращения этой неоднозначности.

1
ответ дан 6 December 2019 в 05:50
поделиться

У Вас не может быть двух различных конструкторов/методов с той же подписью, иначе, как компилятор может определить который метод работать.

Как Zack сказал, я рассмотрю создание класса "опций", куда Вы могли на самом деле передать параметры, содержавшиеся в пользовательском типе. Это означает, что можно в значительной степени передать как много параметров как Вам угодно и сделать то, что Вы любите с опциями, просто быть осторожными Вы не создаете монолитный метод, который пытается сделать все..

Или это или голосование за шаблон "фабрика"..

1
ответ дан 6 December 2019 в 05:50
поделиться

Как был предложен, пользовательские типы способ пойти в этом случае.

1
ответ дан 6 December 2019 в 05:50
поделиться

Вы могли использовать статический метод фабрики:

public static Person fromLogon(String logon) { return new Person(logon, null); }
public static Person fromBadge(String badge) { return new Person(null, badge); }
1
ответ дан 6 December 2019 в 05:50
поделиться

Только вещь, о которой я могу думать для обработки то, что Вы желаете сделать, состоит в том, чтобы иметь к параметрическим усилителям, тот, который описывает тип параметрического усилителя (перечисление с LogonName, BadgeNumer, и т.д.), и вторым является значение параметрического усилителя.

0
ответ дан 6 December 2019 в 05:50
поделиться

Как насчет...

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

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

public Person(Object badgeNumber)
{
    //load logic here...
}
-2
ответ дан 6 December 2019 в 05:50
поделиться

Вы могли переключиться на шаблон стиля фабрики.

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

  ...
}

Или, как предложено, используйте пользовательские типы. Можно также взломать что-то с помощью дженериков, но я не рекомендовал бы это для удобочитаемости.

0
ответ дан 6 December 2019 в 05:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: