вопрос по ООП

alexei.lexx

Новичок
>> hermit_refined Браво за пример!

>> C. К сожалению за ошибки предшественников приходится отвечать нам.

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

Выбор за вами.
 

С.

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

"ООП" и "ООП в PHP4" - две больщие разницы.
 

Андрейка

Senior pomidor developer
alexei.lexx
да понятно, что не вы их придумали.. непонятно только поняли вы что эти дядьки с большой зп там написали или нет.. а выбор очень простой - из за гениальной реализации через общие __get/__set пользоваться этим без крайней необходимости желания не возникает

по поводу "интерфейсов" - расскажите плиз про получение списка свойств без изучения исходников и документации например в той же зендстудии..

-~{}~ 08.12.06 12:59:

hermit_refined
реализуйте еще __clone за компанию..
 

denver

?>Скриптер
FreeSpace
использование геттеров позволяет пользователю класса рассчитывать на то, что интерфейс не поменяется в следующей версии класса, даже если поменяется его внутренняя реализация.
Всё верно, но аттрибуты класса так же как и методы тоже относятся к интерфейсу. И идейно это правильно что есть два способа:
$date = new Date();
echo $date->month; // первый способ
echo $date->getMonth(); //второй способ

В делфях было определенно лучше: для каждого аттрибута можно назначить свои геттер и сеттер (а можно и не назначать):
$date->month = 12;
Который будет работать прозрачно через метод setMonth() если тот был задан как сеттер для данного атрибута.
Не знаю как там в С# (наверное так же).

ЗЫ. Короче главный мой мессадж: не хотелось бы чтоб аттрибуты относились НЕ к интерфейсу, а к реализации. Это нехороший ООП и нужно ждать его фиксов, мне и умным дядькам он не нравится :)

-~{}~ 08.12.06 10:31:

И вообще, всем кому интересны различия:
Свойства класса (там как раз можно узнать много по теме сего топика), поля класса, методы класса
 

denver

?>Скриптер
Главное в интерфейсе - объявление операций, поддерживаемых экземплярами класса. К нему можно добавить объявления других классов, переменных, констант и исключительных ситуаций, уточняющих абстракцию, которую класс должен выражать.
http://vmk.ugatu.ac.ru/book/buch/ch03.htm
Гради Буч
Под интерфейсом класса понимаются элементы-данные, доступные из экземпляров других классов, и методы, которые могут вызываться из других классов.
http://www.object.newmail.ru/oop1.html
Патрикеев Ю. Н.
 

zerkms

TDD infected
Команда форума
denver
определения это конечно очень хорошо, но вы для интереса хотя бы пробовали в пхп в интерфейсах указывать свойства? или разговор из русла пхп вновь уполз куда то в сторону оффтопа и меряния письками? ;)
 

denver

?>Скриптер
Ничего не собирался мерять. А пробовал в ООП php (а ранее object pascal) уже наверное всё, поэтому и написал что мне не нравится.
 

Solid

Drosera anglica
"Первый и, наверное, самый важный этап разработки высококачественного класса - создание адекватного интерфейса. Это подразумевает, что интерфейс должен представлять хорошую абстракцию, скрывающую детали реализации класса.
...под абстракцией понимается представление сложной операции в упрощённой форме. Интерфейс класса -- это абстракция реализации класса, скрытой за интерфейсом. Интерфейс класса должен предоставлять группу методов, чётко согласующихся друг с другом." ("Совешенный код", Стив Макконнелл)

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

FreeSpace

Чукча-читатель
Автор оригинала: denver
В делфях было определенно лучше: для каждого аттрибута можно назначить свои геттер и сеттер (а можно и не назначать):
$date->month = 12;
Который будет работать прозрачно через метод setMonth() если тот был задан как сеттер для данного атрибута.
Не знаю как там в С# (наверное так же).

-~{}~ 08.12.06 10:31:

И вообще, всем кому интересны различия:
Свойства класса (там как раз можно узнать много по теме сего топика), поля класса, методы класса
Всё правильно, в C# дело обстоит примерно так же, только там немного другая конвенция имён.
То, что начинается с большой буквы (Date.Month) - это свойство, а с маленькой (Date.month) - поле.
Свойство может иметь геттер и сеттер. Если сеттера нет, то свойство является readonly.
Поле же может быть константой.
При этом оба могут иметь разные области видимости типа public / private / protected, как обычно.


Но это всё другие ЯП, а автора похоже интересует подход именно в PHP.
В PHP не стоит делать поля (точнее "свойства", говоря языком PHP) public хотя бы из-за динамической типизации и любой умник может написать
$date->month = 'Hello World!';
или ещё лучше -
$date->month = array('Hello', 'World!');

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

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

С.

Продвинутый новичок
любой умник может написать
$date->month = 'Hello World!';
Вы за Протопова не беспокойтесь. Вы за себя беспокойтесь. Лучше бы класс прозрачнее написали, чем защиты ставить там, где это не нужно, и загромождать тем самым код.

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

kirill538

Новичок
Господа, а кто-нибудь может привести практический пример, когда public свойство реально удобнее, чем геттер/сеттер для этого свойства ? Чего-то я пока вообще не понимаю, откуда истоки проблемы :( Чем так принципиально хуже конструкция $obj->setSomeProperty($value) вместо $obj->someProperty = $value, чтобы столько сообщений в теме наплодить ? А вот минусы public свойств вполне очевидны - невозможность определения свойств в interface (усложняется повторное использование, сильно усложняется рефакторингб растет количество необходимой документации), невозможность использования типизации параметра сеттера (особенно если значениями свойств являются объекты), усложнение кода класса с public свойствами (где то ж надо заботится о проверке типа все-таки), и т.п.
 

С.

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

kirill538

Новичок
зачем вам проверка типа данных?
вопрос неясен. если я к примеру в поле класса вместо PDOStatement имею array - они слегка по разному обрабатываются. или я должен каждый раз при обращении к полю проверять тип, или просто укзать нужный в сеттере и забыть. Понятно, что иногда проверка типа не требуется, но требуется - чаще. ИМХО.
Ну дали вам не тот тип, действия вашего класса?
если задан тип параметра - скрипт вывалится с соответствующим сообщением о причине баги. чем это по вашему плохо ?
 

С.

Продвинутый новичок
если задан тип параметра - скрипт вывалится с соответствующим сообщением о причине баги. чем это по вашему плохо ?
Как в отлаженом скрипте на входе окажется не тот тип? (Или у вас объекты методом GET приходят?)

Зачем каждый раз исполнять код, который не нужен в штатном режиме? (Для внештатных режимов есть стандартные сообщения PHP)

Откуда абстрактный класс знает, куда надо вываливать ошибки? (Echo?)

Вот так и получается, понапишут классописатели код, из которого 40% совершенно лишнее жонглирование данными, а потом приходят на форум и спрашивают, что быстрее echo или print.
 

kirill538

Новичок
2С. Вы, я так понимаю, отстаиваете точку зрения правильности public свойств, которые являются частью интерфейса класса.
Как в отлаженом скрипте на входе окажется не тот тип?
Интерфейс кто-то использует. Этот кто-то может через ВНЕШНИЙ интерфейс класса подать на вход что угодно - при чем тут отлаженность скрипта ? Не говоря уж о том, что типизация входных параметров сокращает время собственно отладки/рефакторинга ...

Зачем каждый раз исполнять код, который не нужен в штатном режиме? (Для внештатных режимов есть стандартные сообщения PHP)
Какой ненужный код вы имеете в виду ? c вашей точки зрения типизация параметра метода - большое количество ненужного кода ? есть сведения что function(someInterface $o) работает существенно медленнее чем function($o) ?

Вот так и получается, понапишут классописатели код, из которого 40% совершенно лишнее жонглирование данными, а потом приходят на форум и спрашивают, что быстрее echo или print.
я так понимаю, что привести внятный пример, когда public свойство лучше сеттера/геттера (и объяснить чем именно лучше) у гуру не получается. вместо этого проще обсуждать нужность проверки данных перед их использованием.

приходится признать, что поскольку в защиту public свойств не смогли ни одного аргумента "за" привести (кроме общих мест типа "мне так проще писать") - использовать public свойств - DEPRECATED
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Автор оригинала: hermit_refined
нарушение инкапсуляции здесь приводит к ошибке, которую очень сложно отловить, тем более, если эти строки разнесены по разным классам.
Отличный пример! Продолжим тему маразма :)
PHP:
$a =array('a'=>1);
$ref=&$a['a'];

$b=$a;
$b['a']=2;

echo $a['a'];
AAAAпокалипсис! Всё, прямой доступ к элементам массива признается deprecated по мнению большого брата (aka умные дяди). hermit, kirill ... вы, надеюсь, не обращаетесь напрямую к элементам массива???? Что, обращаетесь???? Ставьте на 1е место в 2do обновление кода для использования get_array_value($array, $key)!

попытка 2я...

PHP:
class X{
    private $x;
    function setX(&$x){
        $this->x=&$x;
    }
}
class Test
{
     protected $member = 0;
     function shout(){
         echo $this->member;
     }
     function work(){
         $this->member=2;
     }
     function __construct(X $x){
         $x->setX($this->member);
     }
}

$x = new X;
$a = new Test($x);

$b = clone $a;

$b->work();

$a->shout();

Ой, мне нечем дышать!
ВЫ ЖЕ НЕ ОБРАЩАЕТЕСЬ НАПРЯМУЮ К ПОЛЯМ КЛАССА ИЗ ЕГО МЕТОДОВ???!

Quick fix проблемы выставления левых ссылок в моменты помрачения разума - вытащить из клавы клавишу 7 :)

Преимущество прямого обращения к полям с использованием __get и __set примером доказать могу, но ... зачем? :)

-~{}~ 29.12.06 22:02:

Автор оригинала: holybg
С.
а если приходят постом?

я не должен проверять?
Нет, конечно! В POSTе приходят правильные данные, отправленные правильными пользователями, которые делают правильный мёд.

-~{}~ 29.12.06 22:04:

P.S. люблю эту ветку форума - несколько минут смеха в день guaranteed ;)
Мое мнение по теме - писать как удобней в каждом конкретном случае, и сделать ветку holy wars, куда переносить дискуссии на тему святого грааля с привлечением авторитетных умных дядей.
 

holybg

Новичок
grigori

удачного смешка и походу Нового года ;)

тх.

п.с. ошибку сделал граматическую (
 
Сверху