Это действительно что, неправильно не используя методы set и методы считывания?

Я являюсь довольно новым в PHP. По некоторым причинам в других типах языков программирования как JAVA у меня нет проблемы с использованием методов set и методов считывания для каждой переменной, но когда я программирую в PHP, вероятно, потому что это настолько гибко, это чувствует отчасти как пустая трата времени. Чувствует себя более простым просто установить атрибуты класса как общественность большую часть времени и управление ими как этот. Вещь состоит в том, что, когда я делаю это как это, я чувствую, что делаю что-то не так и иду вразрез с принципами OO.

Это действительно что, неправильно не используя методы set и методы считывания? Почему или почему нет? Как делают Вас, парни делают это большую часть времени?

15
задан hakre 14 June 2012 в 16:31
поделиться

7 ответов

Основная проблема неиспользования методов доступа к свойствам состоит в том, что если вы обнаружите, что вам когда-нибудь понадобится изменить поле на свойство - например, чтобы сделать его вычисляемым свойством в подклассе - вы сломаете клиентов вашего API. Для опубликованной библиотеки это было бы неприемлемо; для внутреннего - достаточно много работы, чтобы исправить вещи.

Для частного кода или небольших приложений, возможно, было бы просто выпустить его. IDE (или текстовый редактор) позволит вам сгенерировать шаблон доступа и скрыть его с помощью свертывания кода. Это, вероятно, делает использование геттеров и сеттеров механически довольно простым.

Обратите внимание, что некоторые языки программирования имеют функции для синтеза поля по умолчанию + getter + setter - Ruby делает это через метапрограммирование, C # имеет автоматически реализуемые свойства. И Python полностью обходит проблему, позволяя переопределить доступ к атрибуту, позволяя инкапсулировать атрибут в подклассе, который нуждается в нем, вместо того, чтобы беспокоиться об этом заранее. (Этот подход мне нравится больше всего.)

21
ответ дан 30 November 2019 в 23:57
поделиться

Если мы говорим здесь строго о PHP, а не о C #, Java и т. Д. (Где компилятор будет оптимизировать эти вещи), я считаю, что методы получения и установки являются пустой тратой ресурсов, когда вы просто нужно проксировать значение приватного поля и больше ничего не делать.

На моей установке я создал два дрянных класса, один с пятью приватными полями, инкапсулированными пятью парами геттера / сеттера, проксирующими поле (что выглядело почти в точности , как Java-код (как ни странно), а другой с пятью открытыми полями и вызывается memory_get_usage () в конце после создания экземпляра. Скрипт с геттером / сеттерами использовал 59708 байт памяти, а скрипт с открытыми полями использовал 49244 байта.

В контексте библиотеки классов любого значительного размера, такой как структура веб-сайта, эти бесполезные геттеры и сеттеры могут создать огромную черную дыру для памяти. Я разрабатывал фреймворк для своего работодателя на PHP (их выбор, а не мой. Я бы не использовал его для этого, если бы у меня был выбор, но, сказав, что PHP не накладывает на нас каких-либо непреодолимых ограничений) и когда я произвел рефакторинг библиотека классов для использования открытых полей вместо геттеров / сеттеров, весь шебанг в итоге использовал на 25% меньше памяти на запрос как минимум.

Методы 'magic' __get (), __set () и __call () действительно сияют обработка изменений интерфейса. Когда вам нужно перенести поле в метод получения / установки (или метод получения / установки в поле), они могут сделать процесс прозрачным для любого зависимого кода. С интерпретированным языком это ' Немного сложнее найти все виды использования поля или метода даже при достаточно хорошей поддержке чувствительности кода, предоставляемой Eclipse PDT или Netbeans, поэтому магические методы полезны для гарантии того, что старый интерфейс все еще делегирует новые функциональные возможности.

Скажем, у нас есть объект, который был разработан с использованием полей вместо геттеров / сеттеров, и мы хотим переименовать поле с именем 'field' в 'fieldWithBetterName', потому что 'field' был неуместным, или больше не описывал использование точно, или просто просто неправильно. И скажем, мы хотели изменить поле с именем 'field2', чтобы лениво загружать его значение из базы данных, потому что оно не известно изначально с использованием геттера ...

class Test extends Object {
    public $field;
    public $field2;
}

становится

class Test extends Object {
    public $fieldWithBetterName = "LA DI DA";
    private $_field2;

    public function getField2() {
        if ($this->_field2 == null) {
            $this->_field2 = CrapDbLayer::getSomething($this->fieldWithBetterName);
        }
        return $this->_field2;
    }

    public function __get($name) {
        if ($name == 'field')) {
            Logger::log("use of deprecated property... blah blah blah\n".DebugUtils::printBacktrace());
            return $this->fieldWithBetterName;
        }
        elseif ($name == 'field2') {
            Logger::log("use of deprecated property... blah blah blah\n".DebugUtils::printBacktrace());
            return $this->getField2();
        }
        else return parent::__get($name);
    }
}
$t = new Test;
echo $t->field;
echo $t->field2;

(Как примечание, это расширяет Object ' бит - это просто базовый класс, который я использую практически для всего, что имеет объявление __get () и __set (), которое выдает исключение при обращении к необъявленным полям)

Вы можете вернуться назад с помощью __call (). Этот пример довольно хрупкий, но его нетрудно очистить:

class Test extends Object {
    public $field2;

    public function __call($name, $args) {
        if (strpos($name, 'get')===0) {
            $field = lcfirst($name); // cheating, i know. php 5.3 or greater. not hard to do without it though.
            return $this->$field;
        }
        parent::__call($name, $args);
    }
}

Методы getter и setter в PHP хороши, если setter должен что-то делать, или если getter должен что-то загружать или гарантировать, что что-то было создано, или что-то еще, но они не нужны и расточительны, если они не делают ничего, кроме прокси поля, особенно с помощью нескольких методов, подобных приведенным выше, для управления изменениями интерфейса.

15
ответ дан 30 November 2019 в 23:57
поделиться

Существует способ эмулировать get / set без фактического использования класса функции get / set, поэтому ваш код остается аккуратным:

$person->name = 'bob';
echo $person->name;

Посмотрите на этот класс I закодировали.

Как правило, при использовании этого класса вы объявляете все свои свойства защищенными (или частными). Если вы хотите добавить поведение к свойству, скажем, strtolower () + ucfirst () для свойства «name», все, что вам нужно сделать, это объявить защищенную функцию set_name () в вашем классе и поведение должно быть подобрано автоматически. То же самое можно сделать с помощью get_name ().

// Somewhere in your class (that extends my class).
protected function set_name($value) { $this->name = ucfirst(strtolower($value)); }
//

// Now it would store ucfirst(strtolower('bob')) automatically.
$person->name = 'bob';

PS Еще одна интересная вещь: вы можете создавать несуществующие поля, такие как

echo $person->full_name;

, не имея таких полей (если есть функция get_full_name ()).

2
ответ дан 30 November 2019 в 23:57
поделиться

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

17
ответ дан 30 November 2019 в 23:57
поделиться

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

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

7
ответ дан 30 November 2019 в 23:57
поделиться

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

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

1
ответ дан 30 November 2019 в 23:57
поделиться

Рассматривали ли вы использовать магические функции __set / __ get? Используя их, вы можете легко объединить все функции получения / установки только в 2 функции!

3
ответ дан 30 November 2019 в 23:57
поделиться
Другие вопросы по тегам:

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