Какова мотивация для свойств? - PullRequest
3 голосов
/ 03 марта 2009

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

Так что в Java, конечно, у нас нет свойств, и мы пишем методы getThis () и setThat (...).

Что бы мы получили, имея свойства?

Спасибо.

РЕДАКТИРОВАТЬ: другой запрос: какие соглашения об именах возникают в языках со свойствами?

Ответы [ 12 ]

9 голосов
/ 03 марта 2009

Какой из них выглядит более естественным для вас?

// A
person.setAge(25)
// B
person.age = 25;
// or
person.Age = 25; //depending on conventions, but that's beside the point

Большинство людей ответят Б.

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

Вот пример на C # для тех, кто не знаком со свойствами:

class Person
{
    public int Age
    {
        set
        {
            if(value<0)
                throw new ArgumentOutOfRangeException();

            OnChanged();
            age = value;
        }

        get { return age; }
    }

    private int age;
    protected virtual void OnChanged() { // ... }
}

Кроме того, большинство людей всегда используют свойства, а не продвигают публичного члена позже по той же причине, по которой мы всегда используем get / set; нет необходимости переписывать старый клиентский код, привязанный к элементам данных.

7 голосов
/ 03 марта 2009

Синтаксис намного лучше:

button.Location += delta;

чем:

button.setLocation(button.getLocation() + delta);
6 голосов
/ 03 марта 2009

Edit:

Код ниже предполагает, что вы делаете все вручную. В моем примере мира компилятор генерировал бы простые методы get / set и преобразовывал бы весь прямой доступ к этим методам. Если этого не произойдет, то клиентский код придется перекомпилировать, что лишает значительную часть цели.

Оригинал:

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

Например:

public class Foo
{
    public int bar;
}

Если бы мы позже решили проверить «bar», нам нужно было бы сделать это:

public class Foo
{
    private int bar;

    public void setBar(final int val)
    {
        if(val <= 0)
        {
            throw new IllegalArgumentException("val must be > 0, was: " + val);
        }

        bar = val;
    }

    public int getBar()
    {
        return (bar);
    }
}

Но добавление метода set / get нарушило бы весь код. Если бы это было сделано через свойства, то вы могли бы добавить проверку по факту, не нарушая клиентский код.

Мне лично идея не нравится - мне гораздо приятнее идея использовать аннотации и иметь простой набор / получение автоматически с возможностью получать собственные реализации набора / получения по мере необходимости (но я не как скрытые вызовы методов).

3 голосов
/ 03 марта 2009

Две причины:

  1. Очищенный / краткий синтаксис; и
  2. Более четко указывает пользователю класса разницу между состоянием (свойствами) и поведением (методами).
2 голосов
/ 03 марта 2009

В Java геттеры и сеттеры по сути являются свойствами.

В других современных языках (c #) и т. Д. Это просто упрощает синтаксис для работы с / comprehend.

Они не нужны, и в большинстве случаев есть обходные пути.

Это действительно вопрос предпочтений, но если используемый вами язык поддерживает их, я бы порекомендовал их использовать:)

1 голос
/ 03 марта 2009

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

Вы не хотите, чтобы все, кто использует ваш код, должны были перейти с

int x = foo.y;

до

int x = foo.y ();

Это нарушает инкапсуляцию, потому что вы не изменили свой «интерфейс» только своей «реализацией».

1 голос
/ 03 марта 2009

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

Свойства в других языках - это методы, маскирующиеся под особую языковую функцию. В Java свойство различается только по соглашению. Хотя в целом это работает, есть случаи, когда это ограничивает вас. Например, иногда вы можете использовать hasSomething вместо isSomething из getSomething.

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

Также код может быть более компактным, а get и set сгруппированы по дизайну.

1 голос
/ 03 марта 2009

Поначалу я тоже боролся с этим, однако я действительно оценил их. На мой взгляд, свойства позволяют мне естественным образом взаимодействовать с открытыми данными, не теряя инкапсуляцию, предоставляемую методами getter / setter. Другими словами, я могу трактовать свои свойства как поля, но на самом деле не выставляя действительные поля, если я решу не делать этого. С автоматическими свойствами в C # 3.0 это становится еще лучше, как и для большинства полей - где я хочу позволить потребителю читать / записывать данные - у меня есть еще меньше, чтобы написать:

public string Prop { get; set; }

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

public string Prop { get; private set; }

Все это можно сделать с помощью методов получения / установки, но словесность намного выше, а использование гораздо менее естественное.

0 голосов
/ 05 марта 2009

Все дело в привязках

Было время, когда я считал свойства просто синтаксическим сахаром (то есть помогал разработчику, заставляя их печатать немного меньше). По мере того, как я все больше и больше занимался разработкой графического интерфейса и начал использовать связывающие фреймворки (JGoodies, JSR295), я обнаружил, что свойства уровня языка намного, намного больше, чем синтаксический сахар.

В сценарии связывания вы, по сути, определяете правила, в которых говорится, что «свойство X объекта A всегда должно быть равно свойству Y объекта B». Сокращенное обозначение: A.x <-> B.y

Теперь представьте, как бы вы на самом деле написали библиотеку связывания на Java. В настоящее время абсолютно невозможно напрямую ссылаться на «x» или «y» как на языковые примитивы. Вы можете ссылаться на них только как на строки (и получить к ним доступ через отражение). По сути, A. "x" <-> B. "y"

Это вызывает огромные проблемы при рефакторинге кода.

Существуют дополнительные соображения, в том числе правильная реализация уведомлений об изменениях свойств. Если вы посмотрите на мой код, каждому благословенному сеттеру требуется минимум 3 строки, чтобы сделать что-то невероятно простое. Плюс одна из этих трех строк включает еще одну строку:

public void setFoo(Foo foo){
  Foo old = getFoo();
  this.foo = foo;
  changeSupport.firePropertyChange("foo", old, foo);
}

все эти плавающие строки - полный кошмар.

Теперь, представьте, если бы собственность была языком первого класса на языке. Это начинает предоставлять почти бесконечные возможности (например, представьте себе, что нужно напрямую зарегистрировать слушателя с помощью свойства вместо того, чтобы гадить с помощью PropertyChangeSupport и его 3 загадочных методов, которые должны быть добавлены к каждому классу). Представьте себе, что вы можете передать само свойство (не значение свойства, а объект Property) в связующую среду.

Для разработчиков веб-уровня представьте себе веб-инфраструктуру, которая может создавать свои собственные значения идентификатора формы из имен самих свойств (что-то вроде registerFormProperties (myObject.firstname, myObject.lastname, someOtherObject.amount), чтобы разрешить прием туда и обратно заполнение значений свойств объекта при отправке формы обратно на сервер. Сейчас для этого вам нужно будет передать строки, и рефакторинг станет головной болью (рефакторинг фактически становится пугающим, если вы полагаетесь на строки и рефлексию соединяйте вещи).

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

0 голосов
/ 04 марта 2009

Свойства на уровне языка - плохая идея. Для них нет хорошего соглашения, и они скрывают недостатки кода в коде.

...