2013-02-16 2 views
4

Можем ли мы сказать:Разница между свойством и функции или процедуры

type 
    TPerson = class 
    private 
    pName : string; 
    public 
    property Name : string read pName write pName; 
end; 

Равен с:

type 
    TPerson = class 
    private 
    pName : string; 
    public 
    procedure SetName(val: string); 
    function GetName:String; 
end; 

//{... implementing SetName And GetName...} 

??

Пожалуйста, объясните мне, где мы должны использовать «свойство», а где нет. Tnx

+3

В Delphi принято использовать 'F' в качестве префикса для (частных) полей, то есть' FName'. –

+2

Используйте то, что вам больше нравится, в зависимости от того, что удобнее. –

+1

Я бы лично не использовал 'p' для частных полей, потому что' P' уже широко используется как тип указателя, например 'PChar'. 'F' является наиболее используемым. –

ответ

13

Это все о дизайне . Технически «все» вы можете сделать с недвижимостью, вы можете сделать без их, но код будет не таким изящным. Хорошая конструкция также упрощает использование классов и снижает риск ошибок.

Во-первых, ваше сравнение

TPerson = class 
    private 
    FName: string; 
    public 
    property Name: string read FName write FName; 
    end; 

в

TPerson = class 
    private 
    FName: string; 
    public 
    procedure SetName(const Name: string); 
    function GetName: string; 
    end; 

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

TPerson = class 
    private 
    FName: string; 
    procedure SetName(const Name: string); 
    function GetName: string; 
    public 
    property Name: string read GetName write SetName; 
    end; 

Например, если вы пишете контроль, часто необходимо аннулировать (в основном, перекрашивать) управления, когда вы изменяете свойство, скажем, «Цвет свитера» TPerson.Например,

TPerson = class 
    private 
    FSweaterColor: string; 
    procedure SetSweaterColor(const Value: TColor); 
    public 
    property SweaterColor: TColor read FSweaterColor write SetSweaterColor; 
    end; 

    ... 

    implementation 

    procedure TPerson.SetSweaterColor(const Value: TColor); 
    begin 
    if FSweaterColor <> Value then 
    begin 
     FSweaterColor := Value; 
     Invalidate; // causes a repaint of the control 
    end; 
    end; 

Во всяком случае, в чем смысл свойств? Ну, в общем, дело в том, чтобы сделать приятный интерфейс этого класса: он должен быть прост в использовании для кого-то, не заинтересованного в деталях его реализации. Используя свойства, вы можете достичь этой цели. Действительно, чтобы прочитать текущий цвет свитера, вы просто прочитали Anna.SweaterColor, и, чтобы установить его, вы просто Anna.SweaterColor := clRed. Вы не знаете, просто ли это задает переменную или запускает процедуру, и вам все равно. Что касается вас, объект TPerson просто имеет читаемое и настраиваемое свойство, называемое SweaterColor.

Вы также можете создавать свойства, доступные только для чтения (без write) или только для записи (нет read). Но независимо от того, как вы реализуете свойства read и write (если вообще), свойство будет выглядеть одинаково с точки зрения пользователя класса. Он не должен забывать использовать SetSweaterColor или GetSweaterColor (на самом деле, они частные и недоступны для него), но только SweaterColor.

Это также указывает на другое преимущество использования свойств. Публичные и опубликованные свойства видны для пользователей класса, в то время как частные члены не являются (например, поле FSweaterColor и процедура SetSweaterColor). Это хорошо. Потому что теперь вы знаете, что единственный способ для пользователя класса изменить цвет свитера человека - использовать свойство SweaterColor, которое гарантирует перерисовку элемента управления. Если переменная FSweaterColor была общедоступной, пользователь этого класса мог бы задать это и задаться вопросом: «Почему ничего не происходит, когда я меняю цвет свитера?» Конечно, вам не нужны свойства, чтобы получить это преимущество: личное поле FSweaterColor и общественные GetSweaterColor и SetSweaterColor будут делать то же самое, но тогда вам нужно будет написать функцию GetSweaterColor, даже если обработка не требуется для получения цвета , Кроме того, пользователю класса необходимо научиться использовать два идентификатора вместо одного.

Более конкретно, если вы используете программу Delphi для IDE, вы увидите, что в Инспекторе объектов отобразится published property (-y + ies), где вам разрешено читать/изменять их (если применимо). Как это было бы возможно, если бы не свойства?

Все это говорит о том, что иногда вы не используете свойства, хотя можете. Например, если у вас есть свойство «только для чтения», вы можете перейти к единственной публичной функции GetSomething вместо свойства «только для чтения». В конце концов, это спасет вас от некоторой кодировки. Аналогично, если у вас есть свойство только для записи, вы можете пойти с одной общедоступной процедурой SetSomething, которая также сохранит ваш код. Наконец, если у вас есть свойство read/write, которое не требует обработки ни в одну сторону (ни для получения, ни для установки), вы можете просто использовать общедоступную переменную!

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

Использовать в зависимости от того, что вам больше нравится, в зависимости от того, что удобнее.

+1

Это слишком односторонне. Нет никакой большой разницы между Anna.SweaterColor: = clRed и Anna.SetSweaterColor (clRed). Это просто другой синтаксис. Если вы привыкли к последнему, то это хорошо читается. Никаких проблем с этим. Единственные существенные отличия в том, что они могут возвращать поля в читателях свойств, а не писать функции геттера. И потребность в средствах для OI. И я уверен, что они были изобретены, чтобы служить ОИ. –

+1

@ Давид: Я знаю. На самом деле, я думал об этом, пытаясь почистить свою квартиру последние 10 минут. Я добавлю еще немного. –

+0

Программисты на С ++ говорили бы, зачем изобретать язык, чтобы делать то, что мы можем уже делать. Я лично считаю свойства доступными для чтения, но насколько это является внутренним, и насколько выучено поведение? –

0

№ Эти два кода НЕ равны.

Мы используем property, когда мы реализуем класс TPerson как компонент, настраиваемый в инспекторе объектов Delphi. Например, посмотрите на класс TButton. Все вещи, которые вы можете изменить в Object Inspector (Caption, Width, Name и т. Д.), Помечены в исходном коде с помощью ключевого слова property.

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

+5

«Свойство» - это атрибут объекта, в котором вы можете связать действия для чтения и записи своих данных. Ограничений на использование в «TComponents» нет. Напротив, это очень полезно для скрытия деталей реализации класса. –

+0

Но по какой причине заставить нас не использовать «свойство» в простых классах (без компонента)? Потому что он делает то, что нам нужно ... –

+0

@Hamed: Это о * дизайне * класса. Технически, все, что вы можете делать со свойствами, вы можете обойтись без них, но во многих случаях код будет менее изящным. –

1

Свойства - хороший кусок синтаксического сахара. Они эквивалентны парам методов getEnabled и setEnabled, но большинство программистов (и языков программирования) предпочитают свойства вместо этого. Например, в окне завершения кода меньше записей.

Кроме того, они разделяют материал типа «переменный как» (поэтому данные, с которыми должен работать объект) из методов, которые работают с данными.

Свойства не ограничены компонентами, они очень полезны в противном случае. Вы можете определить открытый интерфейс с свойством и реализовать некоторую логику проверки впоследствии. (Невозможно с открытым полем). Но вы используете только две строки кода для простого свойства, по сравнению с 8 строками для этих методов.

Более важным для инспектора объектов является опубликованное ключевое слово, только опубликованные свойства отображаются в OI.

+2

* Кроме того, они разделяют материал типа «переменная типа» (поэтому данные, объект должен работать) из методов, которые работают с данные. * Как и методы getter/setter. –

+0

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

Смежные вопросы