Дизайн конструктора C#

Активность заполняет ActionBar в его методе onCreateOptionsMenu().

Вместо использования setcustomview() просто переопределите onCreateOptionsMenu следующим образом:

@Override    
public boolean onCreateOptionsMenu(Menu menu) {
  MenuInflater inflater = getMenuInflater();
  inflater.inflate(R.menu.mainmenu, menu);
  return true;
}

Если выбрано действие в ActionBar, вызывается метод onOptionsItemSelected(). Он получает выбранное действие в качестве параметра. На основании этой информации ваш код может решить, что делать, например:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
  switch (item.getItemId()) {
    case R.id.menuitem1:
      Toast.makeText(this, "Menu Item 1 selected", Toast.LENGTH_SHORT).show();
      break;
    case R.id.menuitem2:
      Toast.makeText(this, "Menu item 2 selected", Toast.LENGTH_SHORT).show();
      break;
  }
  return true;
}
7
задан Peter Mortensen 26 September 2018 в 17:17
поделиться

9 ответов

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

var myClass = MyClass.LoadFromDirectory(@"C:\temp");

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


Переходя к комментарию снизу к плакату, добавив State, реализация может выглядеть так:

public class MyClass
{

#region Constructors 

    public MyClass(string directory)
    {
        this.Directory = directory;
    }

#endregion

#region Properties

    public MyClassState State {get;private set;}

    private string _directory;

    public string Directory 
    {
        get { return _directory;} 
        private set 
        {
            _directory = value; 
            if (string.IsNullOrEmpty(value)) 
                this.State = MyClassState.Unknown; 
            else 
                this.State = MyClassState.Initialized;
        }
    }

#endregion



    public void LoadFromDirectory()
    {
        if (this.State != MyClassState.Initialized || this.State != MyClassState.Loaded)
            throw new InvalidStateException();

        // Do loading

        this.State = MyClassState.Loaded;
    }

}

public class InvalidStateException : Exception {}


public enum MyClassState
{
    Unknown,
    Initialized,
    Loaded
}
22
ответ дан 6 December 2019 в 06:14
поделиться

Это зависит от обстоятельств. Вы должны оценить основную цель занятия. Какую функцию он выполняет?

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

Как правило, фаза инициализации не должна быть слишком интенсивной. Альтернативный способ сделать это может быть следующим:

// Instantiate the class and get ready to load data from files.
MyClass myClass = new MyClass(@"C:\temp");

// Parse the file collection and load necessary data.
myClass.PopulateData();
5
ответ дан 6 December 2019 в 06:14
поделиться

Это все, что делает ваш класс? Если так, то я бы сказал, что это не имеет значения. Но вполне вероятно, что ваш класс на самом деле делает больше, чем вы показали. Например, есть ли в нем обработка ошибок?

Назначение конструктора - создать объект. Цель метода - выполнить действие. Итак, я голосую за эту форму:

MyClass myClass = new MyClass();
myClass.LoadFromDirectory(@"C:\temp");
1
ответ дан 6 December 2019 в 06:14
поделиться

Я согласен с Ари и другими - разделите их.

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

  • Для вызывающей стороны более ясно, что рабочая функция может занять много времени.
  • Легко предоставить несколько конструкторов для инициализации объекта с различной информацией (например, вы можете иметь возможность передать свой собственный класс (а не строку), который может предоставить имя пути. Или вы можете передать дополнительный параметр, который указывает имя файла с подстановочными знаками для сопоставления, или флаг, чтобы указать, должен ли поиск повторяться в подпапках).
  • Вы избегаете проблем с конструктором. В конструкторе объект сформирован не полностью, поэтому выполнять работу может быть опасно - например, вызов виртуальной функции внутри конструктора - очень плохая идея. Чем меньше кода вы вставляете в конструктор, тем меньше вероятность того, что вы случайно сделаете что-то «плохое».
  • Это более чистый стиль кодирования, чтобы разделить различные поведения / функции на отдельные методы. Разделяйте инициализацию и работу
  • Разделенный класс будет легче поддерживать и реорганизовывать в будущем.
1
ответ дан 6 December 2019 в 06:14
поделиться

Я думаю, вам следует выбрать один из двух подходов, описанных выше ("сначала инициализировать, затем выполнить" vs "пустой init, выполнить с параметрами") в зависимости от того, планируете ли вы повторно использовать один и тот же объект для выполнения той же операции с разные входные данные.
если класс используется только для выполнения задачи с фиксированным параметром, я бы инициализировал его в конструкторе (сделав его доступным только для чтения), а затем выполнял задачу другим методом.
Если вы хотите продолжить выполнение задачи с разными параметрами, я бы поместил ее в метод задачи.

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

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

0
ответ дан 6 December 2019 в 06:14
поделиться

Если основной целью вашего класса не является выполнение ввода-вывода, вам, вероятно, не следует выполнять операции ввода-вывода (потенциально генерируя IOException) в конструкторе.

Рассмотрите возможность разделения класса пополам:

interface IMyDataSource
{
   // ...
}

class FileDataSource: IMyDataSource
{
    public FileDataSource(string path)
    {
        // ...
    }
}

class MyClass
{
    public MyClass(IMyDataSource source)
    {
         // ...
    }
}

IMyDataSource myDS = new FileDataSource(@"C:\temp");
MyClass myClass = new MyClass(myDS);

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

0
ответ дан 6 December 2019 в 06:14
поделиться

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

0
ответ дан 6 December 2019 в 06:14
поделиться

Лично я предпочитаю использовать инициализаторы C # 3.0.

class MyClass {
    public string directory;
    public void Load() {
      // Load files from the current directory
      }
  }

MyClass myClass = new MyClass{ directory = @"C:\temp" };
myClass.Load();

Это дает несколько преимуществ:

  • При создании экземпляра объекта не будет автоматический побочный эффект файловой системы.
  • Все аргументы названы.
  • Все аргументы являются необязательными (но, конечно, мог бросить исключение в Load (), если не определено)
  • Вы можете инициализировать столько свойств, сколько вы хочу в вызове экземпляра без необходимости перегружать конструктор. Например, варианты для рекурсии каталогов, или подстановочный знак для спецификации файла для поиска для.
  • У вас все еще может быть логика в установщике для каталога делать кое-что, но опять же побочные эффекты обычно не очень хорошо.
  • Выполняя файловые операции в отдельный вызов процедуры, вы избегаете проблема неспособности ссылка на свой экземпляр myClass в обработчик исключений.
0
ответ дан 6 December 2019 в 06:14
поделиться

Я собираюсь повторить здесь, ребята, "разделите их". Если это поможет, попробуйте следующее:

  1. Спросите себя: «Что делает этот метод / свойство / поле
  2. Заставить это сделать; не больше, не меньше.

Применяя это здесь, вы получаете следующее:

  1. Конструктор должен создать объект.
  2. Ваш метод должен загружать свои данные из файловой системы.

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

0
ответ дан 6 December 2019 в 06:14
поделиться
Другие вопросы по тегам:

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