Создание методов get и set. Создание методов get и set Get и set методы

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

Интерфейс Set включает следующие методы:

Метод Описание
add(Object o) Добавление элемента в коллекцию, если он отсутствует. Возвращает true, если элемент добавлен.
addAll(Collection c) Добавление элементов коллекции, если они отсутствуют.
clear() Очистка коллекции.
contains(Object o) Проверка присутствия элемента в наборе. Возвращает true, если элемент найден.
containsAll(Collection c) Проверка присутсвия коллекции в наборе. Возвращает true, если все элементы содержатся в наборе.
equals(Object o) Проверка на равенство.
hashCode() Получение hashCode набора.
isEmpty() Проверка наличия элементов. Возвращает true если в коллекции нет ни одного элемента.
iterator() Функция получения итератора коллекции.
remove(Object o) Удаление элемента из набора.
removeAll(Collection c) Удаление из набора всех элементов переданной коллекции.
retainAll(Collection c) Удаление элементов, не принадлежащих переданной коллекции.
size() Количество элементов коллекции
toArray() Преобразование набора в массив элементов.
toArray(T a) Преобразование набора в массив элементов. В отличии от предыдущего метода, который возвращает массив объектов типа Object, данный метод возвращает массив объектов типа, переданного в параметре.

К семейству интерфейса Set относятся HashSet , TreeSet и LinkedHashSet . В множествах Set разные реализации используют разный порядок хранения элементов. В HashSet порядок элементов оптимизирован для быстрого поиска. В контейнере TreeSet объекты хранятся отсортированными по возрастанию. LinkedHashSet хранит элементы в порядке добавления.

Набор данных HashSet

Конструкторы HashSet:

// Создание пустого набора с начальной емкостью (16) и со // значением коэффициента загрузки (0.75) по умолчанию public HashSet(); // Создание множества из элементов коллекции public HashSet(Collection c); // Создание множества с указанной начальной емкостью и со // значением коэффициента загрузки по умолчанию (0.75) public HashSet(int initialCapacity); // Создание множества с указанными начальной емкостью и // коэффициентом загрузки public HashSet(int initialCapacity, float loadFactor);

Методы HashSet

  • public int size()
  • public boolean isEmpty()
  • public boolean add(Object o)
  • public boolean addAll(Collection c)
  • public boolean remove(Object o)
  • public boolean removeAll(Collection c)
  • public boolean contains(Object o)
  • public void clear()
  • public Object clone()
  • public Iterator iterator()
  • public Object toArray()
  • public boolean retainAll(Collection c)

HashSet содержит методы аналогично ArrayList . Исключением является метод add(Object o), который добавляет объект только в том случае, если он отсутствует. Если объект добавлен, то метод add возвращает значение - true, в противном случае false.

Пример использования HashSet:

HashSet hashSet = new HashSet(); hashSet.add("Картофель"); hashSet.add("Морковь"); hashSet.add("Свекла"); hashSet.add("Огурцы"); // Следующая запись не должна попасть в набор hashSet.add("Картофель"); // Вывести в консоль размер набора System.out.println("Размер hashSet = " + hashSet.size()); // Вывести в консоль записи Iterator itr = hashSet.iterator(); while (itr.hasNext()) { System.out.println(itr.next().toString()); }

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

Пример использования HashSet с целочисленными значениями. В набор добавляем значения от 0 до 9 из 25 возможных случайным образом выбранных значений - дублирование не будет.

Random random = new Random(30); Set iset = new HashSet(); for(int i = 0; i < 25; i++) iset.add(random.nextInt(10)); // Вывести в консоль записи Iterator

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

Set set = Collections.synchronizedSet(new HashSet());

Набор данных LinkedHashSet

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

Конструкторы LinkedHashSet:

// Создание пустого набора с начальной емкостью (16) и со значением коэффициента загрузки (0.75) по умолчанию public LinkedHashSet() // Создание множества из элементов коллекции public LinkedHashSet(Collection c) // Создание множества с указанной начальной емкостью и со значением коэффициента загрузки по умолчанию (0.75) public LinkedHashSet(int initialCapacity) // Создание множества с указанными начальной емкостью и коэффициентом загрузки public LinkedHashSet(int initialCapacity, float loadFactor)

Также, как и HashSet , LinkedHashSet не синхронизируется. Поэтому при использовании данной реализации в приложении с множеством потоков, часть из которых может вносить изменения в набор, следует на этапе создания выполнить синхронизацию:

Set set = Collections.synchronizedSet(new LinkedHashSet());

Набор данных TreeSet

Класс TreeSet создаёт коллекцию, которая для хранения элементов использует дерево. Объекты хранятся в отсортированном порядке по возрастанию.

Конструкторы TreeSet:

// Создание пустого древовидного набора, с сортировкой согласно естественному // упорядочиванию его элементов TreeSet() // Создание древовидного набора, содержащего элементы в указанном наборе, // с сортировкой согласно естественному упорядочиванию его элементов. TreeSet(Collection c) // Создание пустого древовидного набора, с сортировкой согласно comparator TreeSet(Comparator comparator) // Создание древовидного набора, содержащего те же самые элементы и использующего // то же самое упорядочивание в качестве указанного сортированного набора TreeSet(SortedSet s)

Методы TreeSet

  • boolean add(Object o)
  • boolean addAll(Collection c)
  • Object ceiling(Object o)
  • void clear()
  • TreeSet clone()
  • Comparator comparator()
  • boolean contains(Object o)
  • Iterator descendingIterator()
  • NavigableSet descendingSet()
  • Object first()
  • Object floor(Object o)
  • SortedSet headSet(E e)
  • NavigableSet headSet(E e, boolean inclusive)
  • Object higher(Object o)
  • boolean isEmpty()
  • Iterator iterator()
  • E last()
  • E lower(E e)
  • E pollFirst()
  • E pollLast()
  • boolean remove(Object o)
  • int size()
  • Spliterator spliterator()
  • NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive)
  • SortedSet subSet(E fromElement, E toElement)
  • SortedSet tailSet(E fromElement)
  • NavigableSet tailSet(E fromElement, boolean inclusive)
  • В следующем измененном примере с использования TreeSet в консоль будут выведены значения в упорядоченном виде.

    SortedSet treeSet = new TreeSet(); treeSet.add("Свекла"); treeSet.add("Огурцы"); treeSet.add("Помидоры"); treeSet.add("Картофель"); treeSet.add("Морковь"); // Данная запись не должна попасть в набор treeSet.add("Картофель"); // Вывести в консоль размер набора System.out.println("Размер treeSet = " + treeSet.size()); // Вывести в консоль записи Iterator itr = treeSet.iterator(); while (itr.hasNext()) { System.out.println(itr.next().toString()); } Random random = new Random(30); SortedSet iset = new TreeSet(); for(int i = 0; i < 25; i++) iset.add(random.nextInt(10)); // Вывести в консоль записи Iterator itr = iset.iterator(); while (itr.hasNext()) { System.out.println(itr.next().toString()); }

    Джозеф Кроуфорд, один из моих читателей, прочитал статью о том, как я не люблю писать getter’ы и setter’ы и предположил, что я могу использовать волшебные методы __get и __set.
    Я скажу вам, почему это не очень хорошая идея, использовать их обычным способом. Кроме того, я собираюсь поведать вам историю, где они действительно оказались полезными, - речь пойдет о создании статических типов в PHP (динамический язык).
    Для тех, кто не знаком с методами __get и __set - это два «магических» метода, которые работают следующим образом:
    class Animal { function __get($property) { //... } function __set($property, $value) { //... } } $cow = new Animal; $cow->weight = "1 ton"; // same as $cow->__set("weight", "1 ton") print $cow->weight; // same as print $cow->__get("weight");

    Как правило, вышеперечисленные методы используются для создания динамических свойств. Какой вывод можно из этого сделать? Если вы хотите создавать любые случайные свойства, просто используйте хэш (он же массив с ключами).
    Что же хорошего в getter’ах и setter’ах?
    Давайте посмотрим:
    class Animal { public $weightInKgs; } $cow = new Animal; $cow->weightInKgs = -100;

    Что? Вес с отрицательным значением? Это с большинства точек зрения неправильно.
    Корова не должна весить меньше 100 кг (я так думаю:). В пределах 1000 - допустимо.
    Как же нам обеспечить такое ограничение.
    Использовать __get и __set - довольно быстрый способ.
    class Animal { private $properties = array(); public function __get($name) { if(!empty($this->properties[$name])) { return $this->properties[$name]; } else { throw new Exception("Undefined property ".$name." referenced."); } } public function __set($name, $value) { if($name == "weight") { if($value < 100) { throw new Exception("The weight is too small!") } } $this->properties[$name] = $value; } } $cow = new Animal; $cow->weightInKgs = -100; // throws an Exception

    А что если у вас есть класс с 10-20 свойствами и проверками для них? В этом случае неприятности неизбежны.
    public function __set($name, $value) { if($name == "weight") { if($value < 100) { throw new Exception("The weight is too small!") } if($this->weight != $weight) { Shepherd::notifyOfWeightChange($cow, $weight); } } if($name == "legs") { if($value != 4) { throw new Exception("The number of legs is too little or too big") } $this->numberOfLegs = $numberOfLegs; $this->numberOfHooves = $numberOfLegs; } if($name == "milkType") { .... you get the idea .... } $this->properties[$name] = $value; }

    И наоборот, getter’ы и setter’ы проявляют себя с лучшей стороны, когда дело доходит до проверки данных.
    class Animal { private $weight; private $numberOfLegs; private $numberOfHooves; public $nickname; public function setNumberOfLegs($numberOfLegs) { if ($numberOfLegs != 100) { throw new Exception("The number of legs is too little or too big"); } $this->numberOfLegs = $numberOfLegs; $this->numberOfHooves = $numberOfLegs; } public function getNumberOfLegs() { return $this->numberOfLegs; } public function setWeight($weight) { if ($weight < 100) { throw new Exception("The weight is too small!"); } if($this->weight != $weight) { Shepherd::notifyOfWeightChange($cow, $weight); } $this->weight = $weight; } public function getWeight() { return $this->weight; } }

    Ничто не идет в сравнение с краткими функциями {get, set;} из C#. Вполне вероятно, такая поддержка скоро появится в PHP, ну а пока не расслабляемся…
    Каждый метод несет ответственность только за собственную область, благодаря этому в коде легче ориентироваться. Все равно получается слишком много кода, но он чище, чем __set-версия. Существует хороший эвристический подход, который заключается в следующем: если ваш метод (функция) занимает больше, чем 1 экран - нужно сокращать. Это улучшит восприятие кода.
    Мы также храним некоторую бизнес-логику. Копыт всегда будет ровно столько, сколько и ног, а если мы заметим изменение веса скотинки, мы тут же уведомим пастуха.
    Так как мы не заботимся о прозвищах коров и не проверяем их, пусть данные будут общедоступными без getter’ов и setter’ов.
    Опять же, я действительно не писал всех этих getter’ов и setter’ов - PHP Storm сделал это за меня. Я просто написал следующее:
    class Animal { private $weight; private $numberOfLegs; }

    И нажал Alt+Insert -> Getters and setters. PHPStorm сгенерировал все автоматически.
    Теперь в виде дополнительного преимущества PHP Storm при работе с getter’ами и setter’ами у меня есть возможность использовать функцию автозаполнения:

    В случае с __get я не имею такой возможности, я могу лишь написать это:
    $cow->wieght = -100

    Теперь корова «весит» (wIEghts) минус 100 кг.
    Я могу забыть, что это вес в кг, достаточно просто написать weight - все будет работать.
    Итак, getter’ы and setter’ы бывают очень даже полезны (но все же не поклоняйтесь им, вы же не программист Java). Если вам просто нужны свободные свойства, используйте массив:
    $cow = array("weight" => 100, "legs" => 4);

    Этот трюк гораздо легче провернуть, чем __get и __set.
    Но, если вы хотите быть уверенным, что ваши данные всегда имеют только допустимые значения, используйте setter’ы с проверкой. При наличии интегрированной среды разработки (IDE), типа PHP Storm, вы будете любить setter’ы, потому что они очень просты в использовании. Вместо $cow->setLegs() для PHP Storm достаточно будет набрать cosl. Да, легко! Нет больше опечаток, и вы можете видеть, какие параметры принимает метод.
    Метод __set имеет и еще один недостаток. Он принимает только 1 параметр. Что делать, если вам нужно 2? Например, как здесь: $store1->setPrice("item-1", 100). Вам необходимо установить цену товара в магазине. Метод __set не позволит вам этого сделать, а setter позволит.

    Чтобы контролировать использование полей, можно создать методы get и set и сделать их общедоступными. Они предоставляют возможность управлять доступом к полю. При этом, поле Age лучше сделать закрытым (private), чтобы к нему нельзя было получить прямой доступ за пределами класса.

    public class Account

    private int age;

    public int GetAge()

    return this.age;

    public void SetAge(int inAge)

    if ((inAge > 0) && (inAge < 120))

    this.age = inAge;

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

    Account s = new Account();

    Console.WriteLine("Возраст: " + s.GetAge());

      1. Использование свойств

    Свойства позволяют сделать управление данными более простым. Свойство Age можно объявить следующим образом:

    public class Account

    private int ageValue;

    if ((value > 0) && (value < 120))

    ageValue = value;

    return ageValue;

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

    Account s = new Account();

    Console.WriteLine("Возраст: " + s.Age);

    Когда свойству Age присваивается значение, вызывается код секции set. Ключевое слово value обозначает значение, которое присваивается свойству. При чтении значения свойства Age происходит вызов кода секции get. Такой подход сочетает преимущества использования методов и позволяет работать со свойствами так же просто, как и с полями класса.

    Проверка правильности данных в свойствах . При попытке задать недопустимое значение возраста (например, 150), приведенный выше код выполнит проверку допустимости и отклонит это значение (никто старше 120 лет не может иметь счет в нашем банке), оставив прежнее значение возраста. Единственный способ узнать, было ли свойству присвоено значение, заключается в проверке значения свойства после этой операции:

    Account s = new Account();

    int newAge = 150;

    if (s.Age != newAge)

    Console.WriteLine("Значение возраста не было установлено");

    Приведенный код пытается присвоить возрасту недопустимое значение 150, после чего проверяется, было ли это значение установлено. Если бы для присваивания значения использовался метод Set, он мог бы вернуть значение false в случае неудачи, а при использовании свойства пользователь должен выполнить чуть больше дополнительной работы.

    Различные способы считывания значения свойства. Свойства позволяют выполнять и другие полезные действия.

    public int AgeInMonths

    return this.ageValue * 12;

    Здесь описано новое свойство AgeInMonths. Оно предназначено только для чтения, так как не содержит секции set. Оно возвращает значение возраста в месяцах, используя то же самое значение, что и свойство Age. Это означает, что можно использовать несколько различных способов для получения одного и того же значения. Можно создать свойства только для чтения без возможности их изменения напрямую, а также свойства только для записи, хотя последние используются редко.

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

    Но при этом, когда мы изменяем текст в элементе TextBlock, мы хотим, чтобы текст на странице Silverlight также изменился, например, когда программа Сумматор выведет на экран результат. Если бы программа просто изменила значение поля, система Silverlight никак не могла бы узнать, что сообщение на экране должно быть обновлено.

    Однако, если Text сделать свойством, при обновлении значения элемента TextBlock запустится соответствующий метод, который может обновить хранимое значение текстового поля и вызвать метод для обновления экрана, чтобы отобразить новое значение. Свойства предоставляют возможность управления объектом при изменении его значения. Простая операция:

    resultTextBlock.Text = "0";

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

    
    © 2024, leally.ru - Твой гид в мире компьютера и интернета