Категории для классов iOS с FMX? [Дубликат]

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

Пример:

Person p = null;
p.Name = "Harry"; // NullReferenceException occurs here.

Вы можно просто избежать этого, проверив, является ли переменная не нулевой:

Person p = null;
if (p!=null)
{
    p.Name = "Harry"; // Not going to run to this point
}

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

Итак, если вы имеете дело со типами значений, NullReferenceExceptions не может произойти. Хотя вам нужно поддерживать оповещение при работе со ссылочными типами!

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

Типы ссылок (эти должны быть проверены):

  • динамический
  • объект
  • string

Типы значений (вы можете просто игнорировать эти):

  • Числовые типы
  • Интегральные типы
  • Типы с плавающей запятой
  • decimal
  • bool
  • Пользовательские структуры

33
задан menjaraz 26 December 2011 в 14:02
поделиться

8 ответов

Я использую их:

  • To вставляет перечисления в классы VCL, которые их не реализуют.
  • To повысить классы VCL.
  • Добавить методы в класс TStrings, чтобы я мог использовать те же методы в моих выведенных списках и в TStringList.
    TGpStringListHelper = class helper for TStringList
    public
      function  Last: string;
      function  Contains(const s: string): boolean;
      function  FetchObject(const s: string): TObject;
      procedure Sort;
      procedure Remove(const s: string);
    end; { TGpStringListHelper }
    
  • Чтобы упростить доступ к полям записи и , удалите литье .
33
ответ дан gabr 28 August 2018 в 01:25
поделиться

Я видел, как они использовались для создания доступных методов класса, согласованных между классами: Добавление Open / Close и Show / Hide ко всем классам данного типа, а не только к активным и видимым свойствам.

0
ответ дан Jamo 28 August 2018 в 01:25
поделиться

Это очень похоже на методы расширения в C # 3 (и VB9). Наилучшее использование, которое я видел для них, это расширения до IEnumerable<T>IQueryable<T>), которые позволяют LINQ работать с произвольными последовательностями:

var query = someOriginalSequence.Where(person => person.Age > 18)
                                .OrderBy(person => person.Name)
                                .Select(person => person.Job);

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

6
ответ дан Jon Skeet 28 August 2018 в 01:25
поделиться

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

type
   TCompetitionToMyClass = class helper for TMyClass
   public
      constructor Convert(base: TCompetition);
   end;

И затем определите конвертер. Одно предостережение: помощник класса не является классом friend . Этот метод будет работать только в том случае, если можно полностью настроить новый объект TMyClass через его общедоступные методы и свойства. Но если вы можете, он работает очень хорошо.

4
ответ дан Mason Wheeler 28 August 2018 в 01:25
поделиться

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

«Самая большая проблема с помощниками класса, начиная с использования их в ваших собственных приложениях, заключается в том, что только один помощник класса для данного класса может быть доступен в любой момент ». ... »То есть, если у вас есть два помощника в области видимости, только компилятор распознает только ОДИН. Вы не получите никаких предупреждений или даже намеков на любые другие помощники, которые могут быть скрыты».

http://davidglassborow.blogspot.com/2006/05/class-helpers-good-or-bad.html

2
ответ дан mjn 28 August 2018 в 01:25
поделиться

В первый раз, когда я помню, что вы испытывали то, что вы называете «помощниками класса», было во время обучения Objective C. Cocoa (инфраструктура Objective C от Apple) использует так называемые «Категории».

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

. Хорошим примером использования категории в какао является так называемый «код ключевых значений (KVC)» и «Key Value Observing (KVO). "

Эта система реализована с использованием двух категорий (NSKeyValueCoding и NSKeyValueObserving). Эти категории определяют и реализуют методы, которые могут быть добавлены в любой класс, который вы хотите. Например, Cocoa добавляет «соответствие» KVC / KVO, используя эти категории для добавления методов в NSArray, таких как:

- (id)valueForKey:(NSString *)key

Класс NSArray не имеет ни объявления, ни реализации этого метода. Однако, используя категорию. Вы можете вызвать этот метод для любого класса NSArray. Вам не требуется подкласс NSArray для получения соответствия KVC / KVO.

NSArray *myArray = [NSArray array]; // Make a new empty array
id myValue = [myArray valueForKey:@"name"]; // Call a method defined in the category

Используя этот метод, вы легко можете добавить поддержку KVC / KVO в свои собственные классы. Интерфейсы Java позволяют добавлять декларации методов, но категории позволяют также добавлять фактические реализации в существующие классы.

3
ответ дан Robert Walker 28 August 2018 в 01:25
поделиться

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

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

Пример:

type
  TStringsHelper = class helper for TStrings
  public
    function IsEmpty: Boolean;
  end;

function TStringsHelper.IsEmpty: Boolean;
begin
  Result := Count = 0;
end;

Каждый раз мы теперь используем экземпляр (подкласс) TStrings и TStringsHelper находится в пределах области действия. У нас есть доступ к методу IsEmpty.

Пример:

procedure TForm1.Button1Click(Sender: TObject);
begin
  if Memo1.Lines.IsEmpty then
    Button1.Caption := 'Empty'
  else
    Button1.Caption := 'Filled';
end;

Примечания:

  • Помощники класса могут быть сохранены в отдельном блоке, поэтому вы можете добавить своих собственных классных помощников классов , Обязательно дайте этим блокам легко запоминающееся имя, например ClassesHelpers, для помощников для модуля Classes.
  • Также есть помощники записи.
  • Если в области есть несколько помощников классов, ожидайте некоторые проблемы, можно использовать только один помощник.
12
ответ дан Toon Krijthe 28 August 2018 в 01:25
поделиться

Как показывает GameCat, TStrings - хороший кандидат, чтобы избежать ввода:

type
  TMyObject = class
  public
    procedure DoSomething;
  end;

  TMyObjectStringsHelper = class helper for TStrings
  private
    function GetMyObject(const Name: string): TMyObject;
    procedure SetMyObject(const Name: string; const Value: TMyObject);
  public
    property MyObject[const Name: string]: TMyObject read GetMyObject write SetMyObject; default;
  end;

function TMyObjectStringsHelper.GetMyObject(const Name: string): TMyObject;
var
  idx: Integer;
begin
  idx := IndexOf(Name);
  if idx < 0 then
    result := nil
  else
    result := Objects[idx] as TMyObject;
end;

procedure TMyObjectStringsHelper.SetMyObject(const Name: string; const Value:
    TMyObject);
var
  idx: Integer;
begin
  idx := IndexOf(Name);
  if idx < 0 then
    AddObject(Name, Value)
  else
    Objects[idx] := Value;
end;

var
  lst: TStrings;
begin
  ...
  lst['MyName'] := TMyObject.Create; 
  ...
  lst['MyName'].DoSomething;
  ...
end;

Вам когда-нибудь приходилось обращаться к многострочным строкам в реестре?

type
  TRegistryHelper = class helper for TRegistry
  public
    function ReadStrings(const ValueName: string): TStringDynArray;
  end;

function TRegistryHelper.ReadStrings(const ValueName: string): TStringDynArray;
var
  DataType: DWord;
  DataSize: DWord;
  Buf: PChar;
  P: PChar;
  Len: Integer;
  I: Integer;
begin
  result := nil;
  if RegQueryValueEx(CurrentKey, PChar(ValueName), nil, @DataType, nil, @DataSize) = ERROR_SUCCESS then begin
    if DataType = REG_MULTI_SZ then begin
      GetMem(Buf, DataSize + 2);
      try
        if RegQueryValueEx(CurrentKey, PChar(ValueName), nil, @DataType, PByte(Buf), @DataSize) = ERROR_SUCCESS then begin
          for I := 0 to 1 do begin
            if Buf[DataSize - 2] <> #0 then begin
              Buf[DataSize] := #0;
              Inc(DataSize);
            end;
          end;

          Len := 0;
          for I := 0 to DataSize - 1 do
            if Buf[I] = #0 then
              Inc(Len);
          Dec(Len);
          if Len > 0 then begin
            SetLength(result, Len);
            P := Buf;
            for I := 0 to Len - 1 do begin
              result[I] := StrPas(P);
              Inc(P, Length(P) + 1);
            end;
          end;
        end;
      finally
        FreeMem(Buf, DataSize);
      end;
    end;
  end;
end;
3
ответ дан Uwe Raabe 28 August 2018 в 01:25
поделиться
Другие вопросы по тегам:

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