использование свойств против геттеров/сеттеров в бизнес-классах

При работе с бизнес-классами, такими как типичные классы Customer и Employee, лучше использовать только геттеры и сеттеры или использовать свойства?

Я перевожу в Delphi (для самообучения) некоторые ООП-примеры из java-книг, в этих примерах всегда есть GetName() и SetName(), свойства не используются.

Теперь я вижу, что если я создаю компонент с опубликованными свойствами, у меня есть очень веская причина использовать свойства, но в обычных классах какой подход лучше? Является ли код более читаемым с геттерами и сеттерами (которые подчеркивают тот факт, что мы читаем/записываем свойство) или со свойствами (которые на первый взгляд можно спутать с методами без параметров)?


person LaBracca    schedule 18.10.2010    source источник
comment
Свойства (в смысле Delphi/C#) являются геттерами и сеттерами. Они просто фактически интегрированы в язык/среду выполнения. Java не имеет такого прямого аналога.   -  person    schedule 19.10.2010
comment
@pst: свойства в Delphi не обязательно являются геттерами и сеттерами. Они могут быть или они могут быть прямым доступом к базовому полю, если вам не нужна дополнительная обработка.   -  person Mason Wheeler    schedule 19.10.2010
comment
Однако разумно иметь в виду, что прямой доступ к полям класса ограничит использование некоторых ОО-методов. Например. свойства в интерфейсах должны быть реализованы через методы, а полиморфизм (виртуальные/абстрактные свойства) требует виртуальных методов получения/установки.   -  person Jørn E. Angeltveit    schedule 19.10.2010


Ответы (4)


Нет. Геттеры и сеттеры есть только в Java, потому что у него нет свойств. Использование свойств делает код намного чище. И затем, если вам нужен геттер или сеттер, вы можете встроить его в свойство, но вам не нужно засорять код доступа кучей вызовов функций.

person Mason Wheeler    schedule 18.10.2010
comment
Все ответы правильные, в любом случае я выбираю один, чтобы сказать, что на вопрос дан ответ. - person LaBracca; 19.10.2010
comment
Вопрос: внутри класса я могу либо читать/записывать приватное поле, либо общедоступное свойство. Есть ли рекомендации всегда использовать поле внутри класса? Потому что, если нет правил, иногда люди пишут поля, иногда собственность, и таким образом свойства становятся запутанным инструментом. В том же классе можно увидеть FName := 'Test' и Name := 'Test'. - person LaBracca; 19.10.2010
comment
Это зависит от того, хотите ли вы, чтобы какой-либо установщик для свойства Name также запускался. Сеттер может инициировать события и т. д., которые вы можете запускать или не запускать в это время. - person Dan Bartlett; 19.10.2010
comment
Как уже говорили другие, свойства являются ценным ресурсом, выходящим далеко за рамки синтаксического сахара, поскольку они обеспечивают краткость, ясность, элегантность и контролируемый доступ. Но есть одно предостережение. Внимательно следите за тем, чтобы любой геттер или сеттер свойства не имел побочных эффектов. Такая скрытая семантика может сильно затруднить использование вашего класса. Сопутствующие убытки гораздо труднее понять и в конечном итоге исправить в свойстве, чем в простых функциях-установщиках-получателях. - person PA.; 19.10.2010

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

Свойства — это элегантный, но мощный способ предоставления контролируемого доступа к полям класса.

Доступ к полям

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

TMyClass = class
private
  FValue: String;
public
  property Value: String read FValue write FValue;
end; 

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

TMyClass = class
private
  FValue: String;
  procedure SetValue(AValue: String);
public
  property Value: String read FValue write SetValue;
end; 

procedure TMyClass.SetValue(AValue: String);
begin
  if AValue = '' 
  then FValue := 'No value!'
  else FValue := AValue;
end;

Управление доступом

Свойства дают вам простой обзор полей только для чтения/записи. Например. только для чтения/неизменяемый класс:

TClient = class
private
  FName: String;
  FSite: String;
  FMail: String;
public
  constructor Create(AName, ASite, AMail: String);
  property Name: String read FName;
  property Site: String read FSite;
  property Mail: String read FMail;
end; 

Полиморфизм

TClient = class
private
  FName: String;
protected
  function GetName: String; virtual; abstract;
public
  property Name: String read GetName write FName;
end; 

TImportantClient = class(TClient)
protected
  function GetName: String; override;
end; 

TArgumentativeClient = class(TClient)
protected
  function GetName: String; override; 
end; 

function TImportantClient.GetName: String; 
begin
  Result := '+++ ' + FName;
end; 

function TArgumentativeClient.GetName: String; 
begin
  Result := ':-( ' + FName;
end; 

{----- ----- ----- ----- -----}
var
  ClientA,
  ClientB: TClient;
begin
  ClientA := TImportantClient.Create;
  ClientB := TArgumentativeClient.Create;

  ClientA.Name := 'Mr. Nice';
  ClientB.Name := 'Mr. Dumbhead';

  ShowMessage(ClientA.Name);
  ShowMessage(ClientB.Name);
end;
{----- ----- ----- ----- -----}

Свойства по умолчанию

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

A := MyStringList[i]:
MyStringList[i] := B;

{ instead of }

A := MyStringList.Strings[i];
MyStringList.Strings[i] := B;

{ or }

A := MyStringList.GetString(i);
MyStringList.SetString(i, B);

Показатель

С помощью ключевого слова Index Delphi будет передавать постоянное значение в качестве аргумента методам получения/установки.

TMyRect = class
private
  FValues: Array[0..3] of Integer;
  function GetProperty(Index: Integer): Integer;
public
  property Top    : Integer  Index 0  read GetProperty;
  property Left   : Integer  Index 1  read GetProperty;
  property Width  : Integer  Index 2  read GetProperty;
  property Height : Integer  Index 3  read GetProperty;
end;


function TMyRect.GetProperty(Index: Integer): Integer;
begin
  Result := FValues[Index];
end; 

Некоторые ресурсы

Есть еще некоторые темы для обсуждения (реализация интерфейсов, хранимые значения, RTTI/свойства времени разработки и т. д.), но этот пост стал немного длинным...

Подробнее можно прочитать на этих сайтах:

person Jørn E. Angeltveit    schedule 19.10.2010
comment
Определенно, свойств гораздо больше. - person Wolf; 15.04.2015

Свойства — большое преимущество Delphi. Я сам довольно много работал с Java и Delphi и определенно выбрал бы Properties. Практически оба подхода в конечном итоге будут делать одно и то же, с той лишь разницей, что свойства выглядят НАМНОГО лучше, чем геттеры/сеттеры.

Я предлагаю вам пойти на свойства, и в полной мере воспользоваться ими!

person Ed.C    schedule 18.10.2010

Это действительно дело вкуса и использования.

Для паскаль-программистов совершенно ясно, читаете вы или записываете значение, поэтому я думаю, что код будет более читаемым, если вы не используете геттеры и сеттеры в стиле java, где вы пишете GetXXX или SetXXX в каждом предложении ваша программа.

Для меня, и я предполагаю, что для большинства программистов на Паскале код будет более читаемым, если вы просто укажете имя свойства, которое вы читаете/пишете, и мы все знаем, что будет вызываться метод Getter или Setter (при необходимости) .

Кроме того, я думаю, что огромным преимуществом (и элегантностью) модели свойств delphi является то, что вы можете получить/установить значение свойства непосредственно из поля. Иметь множество методов Get/Set с помощью всего лишь строки кода, где значение назначенное или прочитанное из поля - пустая трата усилий/времени.

person jachguate    schedule 18.10.2010