2013-09-20 7 views
0

Предположим, у меня есть объект, который я хотел бы скопировать.Справочный параметр Delphi/параметр по умолчанию

interface 

type 
    TPerson = Class(TObject) 
    public 
    first_name: string; 
    last_name: string; 
    address: string; 
    public 
    constructor Create; 
    procedure CopyTo(var s1, s2, s3: string); 
    ... 

implementation 

... 

procedure TPerson.CopyTo(var s1, s2, s3: string) 
begin 
    s1 := first_name; 
    s2 := last_name; 
    s3 := address; 
end; 

end. 

Тогда я могу использовать мой класс, как это:

... 
var 
    name1, name2, address: string; 
begin 
    person := TPerson.Create; 
    person.first_name = 'John'; 
    person.last_name = 'Doe'; 
    person.address = '10 Downing Street'; 
    person.CopyTo(name1, name2, address); 
end; 

Но если я не заинтересован в копировании адрес, я хотел бы иметь возможность использовать его как это

... 
var 
    name1, name2: string; 
begin 
    person := TPerson.Create; 
    person.first_name = 'John'; 
    person.last_name = 'Doe'; 
    person.address = '10 Downing Street'; 
    person.CopyTo(name1, name2); 

    // Some bad legacy code that has a lot more unstructured fields 
end; 

Я подумывал написать перегрузку CopyTo(var s1, s2: string) или использовать столько переменных буфера, сколько числа строк, которые я хочу забыть?

Есть ли более элегантный способ?

Спасибо.

+0

Я не вижу альтернативы перегруженным методам –

+0

Другой альтернативой было объявить строку 'dummy' в разделе' var' и вызвать 'CopyTo (name1, name2, dummy)', который не повлияет на остальную часть кода. –

+0

Но вопрос в основном касался «параметров по умолчанию для параметров, которые я не использую», как сказал Роб Кеннеди. –

ответ

2

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

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

person.first_name = 'John'; 
person.last_name = 'Doe'; 
person.address = '10 Downing Street'; 
name1 := person.first_name; 
name2 := person.last_name; 

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

name1 := 'John'; 
name2 := 'Doe'; 
person := TPerson.Create(name1, name2, '10 Downing Street'); 
+0

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

+1

Ищите «быстрый способ сделать то, что сделали» - вот что достало вам плохо написанный код. Вы можете продолжить с этим, но знаете, что у вас будет еще больше * технического долга *. В какой-то момент вам придется вернуть его обратно. Подумайте о том, может ли небольшое улучшение теперь облегчить запись лучшего кода в будущем. –

0

По-моему, использование перегрузок с некоторыми более описательными переменными - лучший подход. Я всегда стараюсь сделать intention revealing interfaces и называет

+0

Не понимаю. В этом вопросе предлагается более элегантный способ извлечения частичных списков значений из объекта. Имена 'name1' и' name2' кажутся мне адекватно описательными, и их изменение никак не повлияет на переменную 'address', но это тот, который выборочно отсутствует. Может быть, вы могли бы привести пример того, что вы предлагаете. –

+2

@Rob Параметры 'CopyTo' называются' s1', 's2' и' s3'. –

+0

Итак, по существу, @David, в этом ответе, 's/variables/names parameters /'? Я не уверен, что это очень понравится. –

0

Скажем, у меня есть объект, который я хотел бы скопировать.

Строго говоря, это не то, что вы здесь делаете. Конечно, все копируется, а переменным, а не объекту. И учитывая, что ссылочные параметры, связанные с использованием variabels, мешают вам определять значения по умолчанию, я предлагаю сделать ваше копирование фактической копией всего объекта.

Разработайте TPerson класс типа TPersistent, который имеет вид механизма копирования сборки в (будет осуществляться/расширена проектировщиком) и продлить конструктор с параметрами по умолчанию:

type 
    TPerson = Class(TPersistent) 
    private 
    FFirstName: String; 
    FLastName: String; 
    FAddress: String; 
    public 
    procedure Assign(Source: TPersistent); override; 
    constructor Create(AFirstName: String = ''; ALastName: String = ''; 
     AAddress: String = ''); overload; 
    constructor Create(APerson: TPerson); overload; 
    property FirstName: String read FFirstName write FFirstName; 
    property LastName: String read FLastName write FLastName; 
    property Address: String read FAddress write FAddress; 
    end; 

procedure TPerson.Assign(Source: TPersistent); 
begin 
    if Source is TPerson then 
    begin 
    FFirstName := TPerson(Source).FFirstName; 
    FLastName := TPerson(Source).FLastName; 
    FAddress := TPerson(Source).FAddress; 
    end 
    else 
    inherited Assign(Source); 
end; 

constructor TPerson.Create(AFirstName, ALastName, AAddress: String); 
begin 
    inherited Create; 
    FFirstName := AFirstName; 
    FLastName := ALastName; 
    FAddress := AAddress; 
end; 

constructor TPerson.Create(APerson: TPerson); 
begin 
    inherited Create; 
    Assign(APerson); 
end; 

И теперь, ваш possibillities варьируются от:

procedure Example1; 
var 
    Person: TPerson; 
    PersonCopy: TPerson; 
begin 
    Person := TPerson.Create; 
    Person.FirstName := 'John'; 
    Person.LastName := 'Doe'; 
    Person.Address := '10 Downing Street'; 
    PersonCopy := TPerson.Create; 
    PersonCopy.Assign(Person); 
    //... 
end; 

к:

procedure Example2; 
var 
    Person: TPerson; 
    PersonCopy: TPerson; 
begin 
    Person := TPerson.Create('John', 'Doe'); 
    PersonCopy := TPerson.Create(Person); 
    //... 
end; 
Смежные вопросы