Является ли этот шаблон определения класса + конструктор чрезмерно избыточным? - PullRequest
2 голосов
/ 24 декабря 2010

Я часто сталкиваюсь с шаблоном, похожим на этот:

class Person {
    public string firstName, lastName;
    public Person(string firstName, string lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

Это кажется чрезмерно избыточным (я думаю, что набирать «firstName» один раз, вместо трех может быть достаточно…), но я не могу думать,правильной альтернативы.Есть идеи?Может быть, я просто не знаю об определенном шаблоне дизайна, который я должен использовать здесь?

Правка - я думаю, что мне нужно немного проработать.Я не спрашиваю, как сделать пример кода «лучше», а скорее «короче».В своем текущем состоянии все имена членов появляются 4 раза (объявление, инициализация, аргументы конструктора), и это выглядит довольно избыточно.Поэтому мне интересно, есть ли шаблон (или семантический сахар) для получения (примерно) того же поведения, но с меньшим количеством вздутия.
Я прошу прощения за то, что изначально неясен.

Правка - C # 3.0 ДэйваПример инициализации довольно хорош, но я все еще надеюсь на более общий ответ.:)

Редактировать - теперь я понимаю, что некоторые языки допускают меньше многословных реализаций;Java и C # не могут.

Ответы [ 4 ]

4 голосов
/ 24 декабря 2010

Это зависит от того, что вы пытаетесь выполнить, и от того, какие конкретные значения имеют , которые будут установлены по какой-то причине при создании объекта.

Если вы хотите, чтобы значения удерживались толькочтобы быть установленным на конструкцию, вы должны объявить класс так, как вы это сделали:

class Person
{
    public string FirstName { get; private set; }
    public string Surname { get; private set; }

    public Person(string firstName, string surname)
    {
        // properties are read-only so must be set as part of the constructor
        this.FirstName = firstName;
        this.Surname = surname;
    }
}

Если есть какое-то требование, чтобы свойства были установлены на конструкцию, то вы также должны определить класс, как вы это сделали.Однако вы также можете сделать возможным изменение этих значений позже.

class Person
{
    public string FirstName { get; set; }
    public string Surname { get; set; }

    public Person(string firstName, string surname)
    {            
        this.FirstName = firstName;
        this.Surname = surname;
    }
}

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

class Person
{
    public string FirstName { get; set; }
    public string Surname { get; set; }

    public Person()
    {
    }
}

В C # (от 3 и выше) вы все равно можете установить эти свойства во время создания, но я не уверен, какие функции есть в других языках, которые могут отражать это:

var myPerson = new Person
{
    FirstName = "Test",
    Surname = "Test2",
};

Все примеры приведены на C #, но в целом должны содержать значение ООП.

1 голос
/ 24 декабря 2010

Общий шаблон, вероятно, «используйте хороший язык программирования».Например, эта единственная строка Scala примерно эквивалентна тому, что вы написали выше:

class Person(var firstName: String, var lastName: String)

Вы можете запустить декомпилятор Java над сгенерированным файлом Person.class, чтобы увидеть, что вам нужно написать в Java дляполучить ту же функциональность:

public class Person {
    private String firstName, lastName;

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String paramString) {
        this.firstName = paramString;
    }

    public String getLastName() {
        return this.lastName;
    }

    public void setLastName(String paramString) {
        this.lastName = paramString;
    }

    public Person(String firstName, String lastName) {
        setFirstName(firstName);
        setLastName(lastName);
    }
}

Имена методов будут немного отличаться (вместо getFirstName и setFirstName Scala использует только firstName и firstName_=, последний из которых, в свою очередь, кодируется какfirstName_$eq, поскольку это недопустимо в Java), но намерение то же самое.

Если вы можете сделать свой класс case class, вы также автоматически получите правильные реализации для equals и hashCode.

В Ruby вы написали бы:

Person = Struct.new(:first_name, :last:name)

и снова получили бы нечто, очень похожее на то, что вы получите в своем примере на Java.Struct.new фактически синтезирует правильный класс, который выглядит примерно так:

class Person
  attr_accessor :first_name, :last_name

  def initialize(first_name, last_name)
    self.first_name, self.last_name = first_name, last_name
  end
end
1 голос
/ 24 декабря 2010

Я не спрашиваю, как сделать пример кода «лучше», а скорее «короче».В своем текущем состоянии все имена членов появляются 4 раза (объявление, инициализация, аргументы конструктора), и это выглядит довольно избыточно.Поэтому мне интересно, есть ли шаблон (или семантический сахар), чтобы получить (примерно) такое же поведение, но с меньшим раздуванием.

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

Например, в Scala вы можете определить это как класс case и потерять все повторения:

case class Person(firstName: String, lastName: String)

Аналогично, в Ruby вы можете сделать определение класса довольно коротким, используя атрибуты доступа:

class Person
  attr_accessor :first_name, :last_name
end

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

0 голосов
/ 25 декабря 2010

Некоторые языки разработаны так, чтобы быть многословными, и обычно они не позволяют вам это исправить.

Что касается объявлений типов, то Java заставляет вас не только указывать, но и повторять очевидное.Вывод типов в основном может исправить это, если вы хотите использовать такие языки, как Scala.

В Javascript, где у вас нет ни статических типов, ни классов, конструкторы являются просто функциями, которые создают объекты, и это будет выглядеть так:

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...