Подтвердить что ты не робот

Параметры конструктора и параметры метода?

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

Я постараюсь задать контекст для моего вопроса:

public interface ICopier
{
   void Copy();
}

public class FileCopier : ICopier
{
   String m_source;
   String m_destiniation;

   FileCopier(String source_, String destination_)
   {
        m_source = source_;
        m_destiniation = destiniation_;
   }

   public void Copy()
   {
        File.Copy(m_source, m_destiniation, true);
   }
}

Или должен ли FileCopier.Copy() принимать исходные_и_почтой_ как параметры метода?

Я хочу, чтобы эти классы были максимально абстрактными.

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

Спасибо!

4b9b3361

Ответ 1

Передайте их методу. Таким образом, вы можете скопировать несколько мест, не переустанавливая FileCopier и выполнять другие операции, которые могут потребовать другие параметры. В этом случае вы можете сделать методы статичными, поэтому никакой инстанцирования не требуется вообще. Вы заметили, что это работает, например, для класса С# File.

Ответ 2

Это зависит:)

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

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

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

Итак, я хотел бы сделать инкапсуляцию данных, передав их в качестве параметров конструктора, чтобы иметь простые API. Тогда он будет выглядеть как объект Command.

Ответ 3

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

Ответ 4

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

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

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

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

С другой стороны, если вам нужно управлять состоянием для каждой операции копирования, например отслеживанием прогресса, отслеживанием ошибок, обратными вызовами завершения и т.д., было бы разумнее передать параметры в конструкторе, но также добавить принудительное выполнение, которое будет запретить Copy вызывать более одного раза.

Ответ 5

Старый вопрос, но кажется, что многие люди отвечают, не учитывая намерения абстракции ICopier. Как заявил Saurabh, поэтому его копирование (String, String) (и настройка интерфейса соответственно) будет означать, что любые другие реализации ICopier будут ограничены использованием этого метода.

Что делать, если вам нужно расширить его, чтобы создать EmailCopier, который отправляет файл из источника в список писем вместо целевого файла? Вы можете написать хакерский метод, который продолжает принимать (String, String):

ICopier copier = new EmailCopier();
copier.copy(sourceFile, "[email protected],[email protected]");

Или вы можете поместить всю эту информацию в конструктор, используя правильные структуры данных и простую команду copy():

ICopier copier = new EmailCopier("sourceFile', aListOfEmails);
copier.copy();

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

Ответ 6

Это все об использовании;

Какой из них вам легче?

FileCopier f = new FileCopier(sourceFrom,sourceTo);
f.Copy();

или

FileCopier f = new FileCopier();
f.Copy(sourceFrom,sourceTo);

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

Ответ 7

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

FileCopier fc = new FileCopier(src, dest);
fc.Copy();

против

FileCopier.Copy(src, dest);

Лучшим примером того, о чем я говорю, является System.Math class в .NET Framework. System.IO.File класс также работает таким образом (и возникает вопрос, почему вы его воссоздаете).

Ответ 8

Я бы предпочел, чтобы конструктор принимал аргументы, поскольку ответственность за FileCopier заключается в том, чтобы скопировать файл из источника в пункт назначения, а интерфейс, который он реализует, можно использовать с другими классами hetrogeneous, поэтому, если вы предоставите параметры функции Copy(), это станет более конкретным, но в текущем состоянии его можно использовать во многих местах, для чего требуется функция копирования

Ответ 9

wrt в ваш контекст, лучше передать параметр в метод, если у вас есть только метод копирования внутри вашего класса. Но передача их конструктору может быть полезна, если вам нужно выполнить несколько операций с использованием одного и того же объекта.

например:

    public class FileCopier : ICopier
    {
       String m_source;
       String m_destiniation;

       FileCopier(String source_, String destination_)
       {
            m_source = source_;
            m_destiniation = destiniation_;
       }

       public void Copy()
       {
            File.Copy(m_source, m_destiniation, true);
       }

       public void DeleteSource()
       {
       }

       public void DeleteCestination()
       {
       }

  etc...
    }

Ответ 10

Странно, что никто не упоминал о вашем интерфейсе ICopier.

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

Если ICopier запрашивает реализацию Copy(), он должен также предоставить значения/аргументы, необходимые для выполнения задачи.

Ответ 11

Недавно я нашел следующее правило "Если параметр используется из-за реализации, тогда поместите его в конструктор, если этот параметр используется из-за интерфейса, тогда поместите его в метод".

Проблема заключается в том, что у вас нет комментариев выше метода Copy:

  • Если он "скопирует один файл из места назначения в источник", вы должны добавить параметры источника и назначения, потому что вы говорите об этом в описании интерфейса.
  • если он "когда-то переделает что-то", то добавьте его в конструктор, потому что вам понадобится только ваша реализация FileCopier.