вопрос по ООП

grigori
Что значит "отложенное"?
вы так много кричали RTFM. ну чтож - тоже извольте почитать мануал, погуглить.

Вы знакомы с файловой системой Unix? При записи в файл по ссылке тоже должно происходить "отложенное копирование"?
при чём здесь фс униксов?

при чём здесь копипаст мануала и выделение того что ссылки не являются указателями?
Должно по каким правилам? Или Вы лично ожидаете этого по аналогии с практикой на _других_ языках?
я это ожидаю исходя из здравого смысла
Если с точки зрения работы скрипта - то $a['a'] и $ref становятся идентичными и ведут себя как ссылки (что и видно из примера).
угу, $a['a'] и $ref являются ссылками. однако почему $b, которое не является ссылкой, модифицирует значение $a['a'] ?

PHP:
$a = 1;
$ref =& $a;

$b = $a;

$b = 2;

var_dump($a);

что должен вывести этот код согласно вашим рассуждениям?
 
Имхо исходя из здравого смысла (по крайней мере как я его вижу) $a должен оставаться массивом, $b должен быть копией его содержимого, а $ref ссылкой на $a.
(не знаю как на других языках, в бейсике например этого вообще нету)

Однако на практике после того как $ref становится ссылкой $a так-же становится ссылкой, а $b становится тем же чем и $a (т.е ссылкой) что ИМХО не правильно так как никто не просил менять тип $a на него просто сослались...
 
Автор оригинала: grigori
PHP:
$a =array('a'=>1);
$ref=&$a['a'];

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

echo $a['a'];
AAAAпокалипсис! Всё, прямой доступ к элементам массива признается deprecated по мнению большого брата (aka умные дяди).
я написал пример как раз на основе аналогичного поведения массивов, вы обратили.
ну и? разве не апокалипсис? неужели вы думаете, что если по-моему мнению публичные свойства класса - зло, я благоволю к массивам?
да, они замечательно могут использоваться внутри классов, даже могут передаваться между объектами в качестве совокупности данных - только неизменяемой, ибо если с этими данными связанно хоть какое-то поведение, мы обязаны их инкапсулировать в объект.
в иных случаях, массивы - черные ящики. мы не знаем, что в них есть и чего в них нет. их использование на глобальном уровне - в большом проекте грозит сумасшествием для разработчиков. даже безо всяких ссылок.

(кстати, есть такая забавная деталь - суперглобальные массивы, которые при register_globals = off состоят из нормальных переменных, при register_globals = on - становятся состоящими из ссылок. в свое время я убил полдня на отладку в одном - признаться, не ахти написанном приложении - чтобы понять, почему все работает не так, как expected.)
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);
     }
}
вы бредите, не понимая к тому же смысла моего примера.
во-первых, в моем примере разработчик класса Test ни в чем не виноват (кроме того, что оставил публичные свойства), тем не менее непредсказуемое поведение наблюдается именно при работе с объектами этого класса. в вашем - (оставляя за скобками некорректность такой работы с объектами, как в вашем конструкторе класса Test) - разработчик видел интерфейс класса X, и если он передал защищенное свойство по ссылке другому объекту - он профнепригоден.
во-вторых, в вашем примере баг инкапсулирован в классе Test - достаточно заглянуть в конструктор и посмотреть на интерфейс класса X, чтобы понять, в чем дело (да-да, ошибки в ООП объектно-ориентированные и инкапсулированные). а куда разработчику в моем примере податься?..

All
странно, что мой пример с объектами никого не смутил, а с массивами - вызвал панику :-))
по ссылке Преведа всё очень хорошо и правильно расписано. В мануале (искал полтора года назад) вразумительных объяснений нет, только в комментариях пользователей и на bugs.php.net с классической благодарностью за интерес к php :-))
такое устройство ссылок, на мой взгляд, является совершенно дурацким, но если смотреть исходники, понятно, почему так было сделано.
слава богу, в php 5 нет никакой необходимости использовать ссылки вовсе (кроме некоторых оптимизаций внутри классов или отдельных методов, где это поведение вполне контролируется).
 
Так я не понял, что же лучше?

Обращаться напрямую к публичным свойствам класса или использовать методы интерфейса для установки значений private свойств класса?
 
Имхо публичные свойства класса для того и сделаны были чтоб к ним обращаться, но со стороны самой концепции ООП это не совсем "красиво"
 
Автор оригинала: Bermuda
Так я не понял, что же лучше?...
Если использовать методы - появляется возможность информировать объект о том, что его свойство кем-то использовано.
Если не использовать - такой возможности нет.
Все это - вопрос практической необходимости.
 
Ок, рассмотрим пример из жизни.

Класс: коты
Свойство: цвет = серый
Задача -- покрасить кота в зеленый цвет.

Вариант 1.
//Беру кота и крашу его в зеленый цвет
$коты->цвет = зелёный;

Вариант 2.
//Беру кота и прошу его поркасить самого себя в зеленый цвет
$коты->покрасьСебя(зелёный);

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

-~{}~ 12.01.07 13:30:

Автор оригинала: Shturm
Если использовать методы - появляется возможность информировать объект о том, что его свойство кем-то использовано.
Да, это несомненно плюс.
 
Во-первых, попробуйте сделать

PHP:
interface TheCat {
   public $color = null;
}

получите ошибку. Это означает, что вы не можете гарантировать наличие публичных атрибутов в реализации класса. Вы можете гарантировать только наличие методов.
Допустим в системе есть
PHP:
class CatColourer {
     public function colour(TheCat $cat,$newColor){

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

Реализация colour не может знать, какой конкретно атрибут следует использовать для задания нового цвета. А вот если бы в интерфейсе TheCat был декларирован setColor/getColor то в реализации метода colour никаких проблем бы не возникало.

Далее... Допустим у нас есть класс, реализующий список элементов на многомерных массивах. Для доступа к элементам мы используем публичные атрибуты. В один прекрасный момент нас осеняет и мы хотим сделать рефакторинг этого класса, разделяя его на два - собсно менеджер элементов и отдельный элемент списка. А потом вдруг спохватываемся, представляя сколько придется лазить по коду всех проектов, которые используют наш список, в целях исправления прямого доступа на доступ через методы делегаты (правильный рефакторинг) или через публичное свойство-хранилище объектов-элементов, с целью обращения к их атрибутам или методам (неправильный рефакторинг).

Если бы мы опирались на интерфейс, мы бы не волновались что наши проекты рухнут после рефакторинга класса списка. Использование публичных атрибутов усложняет рефакторинг а в некоторых случаях делают его просто не целесообразным.
 
zerkms
пардон, не обратил внимание, что это не объкект )
извиняюсь :)
 
Выскажу своё мнение, по поводу кода демонстрирующего "странное" поведение ссылок.
Когда я делаю операцию копирования (= для простых типов и clone для объектов), я ожидаю получить сущность представляющую собой точную копию объекта на момент копирования (за исключением ресурсов, которые конечно всегда передаются по ссылке).
Я считаю, что приведённый код демонстрирует баг, связанный с текущим алгоритмом работы ZE со ссылками.
С моей точки зрения, даже если баг (багоподобное поведение) описано в документации, бегом оно не перестаёт быть.
 
ONK
Полностью согласен (о чём уже сказал выше) операция копирования должна быть копированием а не чем-то ещё...
 
Автор оригинала: Vladson
Имхо публичные свойства класса для того и сделаны были чтоб к ним обращаться, но со стороны самой концепции ООП это не совсем "красиво"
Это на каком соборе Церкви ООП такой догмат о некрасивости ввели? Я что-то пропустил?

Здесь так и не предложили ни одной причины, почему НАДО обращатся через методы, кроме того, что потом де переделывать легче. Чисто кодеровский подход: не как лучше работать будет, а как переделывать...

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

Тем более, что "со стороны самой концепции ООП" (C) Vladson) переделка одного класса не должно быть такой уж и большой проблемой. Изменение его поведение не должно коренным образом рушить всю структуру проекта. Если это у вас происходит, то значит вы оборачиваете GLOBALS в объекты и выдаете это за ООП.
 
С., вам уже множество примеров привели, почему внутреннюю начинку объекта стоит скрывать за интерфейсом методов. Если вы ещё не видите причин, по которым в большинстве случаев стоит избегать обращения к свойствам объекта напрямую, то возможно вам стоит переквалифицироваться в дворника, т.к. как вам нехватает способности к обучению.
Судя по вашим ответам у вас просто нет опыта написания хоть чуть чуть ОО приложений.
Класс может быть спроектирован верно "на момент его проектирования", но время и обстоятельства изменяют требования к его функциональности. Практика показывает что удобство/простота/скорость внедрения новой функциональности при полностью инкапсулированной внутренней структуре объекта на порядок выше, чем в случае, когда в коде приложения напрямую залезают в потроха объекта и тем самым связывают/фиксируют его внутреннюю структуру. При правильном подходе, фактически процесс добавления новых функциональностей сводится к редактированию кода самого объекта, и добавлению новых вариантов использования в прикладном коде. Не надо забывать, что сложность внутренней структуры одного объекта может быть на порядок выше, чем сложность всего прикладного кода, в котором он используется.

Другое дело, что назначение объектов может быть совершенно разным, и некоторых случаях объект создаётся специально, чтобы иметь прямой доступ к его свойствам, но это отдельная история.
 
Согласен с С.:
Есло класс изначально спроектирован верно (чего кодер сделать очевидно не может), то ничего переделывать не надо будет. Если вдруг обнаруживается, что в проекте класса недочет, то не заплаты надо лепить на него, а брать и кропотливо приводить его в соответствие. Да, лазить по программе. Да, менять код.
Допустим, система работает с классом Microscope, но вдруг выясняется что этот класс должен работать как Hummer. Есть два варианта решения:

1. Осознать изменение требований или ошибки первоначального проектирования, и перепроектировать ВСЮ систему (долго, дорого, качественно).
2. Осознать изменение требований или ошибки первоначального проектирования, и переписать _реализацию_ класса Microscope так, чтобы вел себя как Hummer, но только чтобы всю систему не трогать (быстро, дешево, после нас хоть потоп).

В целом:
- да, изменять класс (хоть и кардинально) состоящий ТОЛЬКО из методов, не меняя интерфейс, проще.
- менять-то проще, но стройность класса (и в целом фундамент системы) от этого размывается, так что (стратегически) бывает лучше перепроектировать систему.

Конечно, правильное решение лежит где-то между суммой затрат на рефакторинг и суммой затрат на дальнейшую поддержку системы.
 
перенес в теорию. полезный топик. не без лишнего, но в общем и целом - пример топика, каких хотелось бы побольше на форуме.
 
denver, Так не бывает, тоесть наверное бывает, но я не имею литературных слов, чтобы полностью выразить своё мнение о таком подходе к проектированию приложения.

Если рассматривать нормальный процесс проектирования / разработки приложения, идущий от общего к частному, то в случае с микроскопом, он всегда будет оставаться микроскопом. Просто в определённый момент времени разработчики проекта могут придти к решению, что для решения их задач нужен не оптический микроскоп, а электронный. И что мы имеем? микроскоп должен поддерживать теже операции юстировки иследуемого объекта, фокусировки и получения кадра изображения, только в отличии от оптического микроскопа внутри него вместо линз будет вакуумная колба со сканирующим электронным пучком. Надеюсь на этом примере понятно, почему не стоит залезать внутрь специализированного объекта?
 
Ура! Новый, самый модный Holy WAR продолжается! :)

Поддерживаю C и denver.

whirlwind,
попробуйте сделать interface
Товарисч из Харькова :) не понимает ... как отсутсвие поддержки публичных свойств у интерфейсов доказывает нецелесообразность использования полей.
Напиши
PHP:
abstract class A{
    public $x=2;
    abstract function abc();
}
и требуй, где надо, дочек класса А ...
Или тебе так уж часто нужна реализация множественных интерфейсов?

zerkms,
с какой стати ссылка?
в PHP любое копирование - ссылка.

ONK,
приведённый код демонстрирует баг, связанный с текущим алгоритмом работы ZE со ссылками
Он демонстрирует текущий алгоритм работы. Баг это или нет ... а давайте голосование сделаем? :)
Я за то, что это фича!

-~{}~ 13.01.07 18:37:

Автор оригинала: ONK
микроскоп должен поддерживать теже операции ...
только в отличии от оптического микроскопа внутри него вместо линз будет вакуумная колба...
Надеюсь на этом примере понятно, почему не стоит залезать внутрь специализированного объекта?
Не понятно, блин ... но я из Харькова, мне можно :)
У меня есть class User, у него есть поле user_id ... почему я не могу сделать его полем, а должен делать метод getUserId ?
Много лет писал
PHP:
class XXX{
isRegistered(){
    return ($this->user_id>0);
}
...
в коде:
if ($UserData->isRegistered()) ...
Пол-года назад плюнул, теперь пишу
if ($UserData->user_id)

В рамках текущей сессии user_id - константа... новый пользователь - новый объект.
Нафига мне эти навороты с методами?

Так же с first_name, last_name, email ...

А у микроскопа линзы и колбу делать полями не надо. Полем надо делать идентификатор типа микроскопа. Все варианты значений типа определить константами класса. А если у кодера помрачение разума и он указал левое значение типа - то это его личные сексуальные трудности.
 
Сверху