[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Вопрос о наследовании
kirik
Решил заняться более подробным изучением классов, появился вопрос о наследовании.

Имею код:
Свернутый текст
PHP
Class Engine {
    protected 
$variable 'not set';

    function 
show()
    {
        echo 
"\nEngine - ".$this->variable;
    }

    function 
set($var)
    {
        
$this->variable $var;
    }
}

Class 
Ext extends Engine {
    function 
show1()
    {
        echo 
"\nExt - ".$this->variable;
    }

    function 
set1($var)
    {
        
$this->variable $var;
    }
}

Class 
Ext2 extends Engine {
    function 
show2()
    {
        echo 
"\nExt2 - ".$this->variable;
    }
}

$Engine = New Engine;
$Ext = New Ext;
$Ext2 = New Ext2;

$Ext->set1('test');
$Engine->show();

$Engine->set('test1');
$Engine->show();

$Ext->set1('test2');
$Ext->show1();

$Engine->set('test3');
$Ext->show1();

$Ext2->show2();


Результат:
Цитата
Engine - not set
Engine - test1
Ext - test2
Ext - test2
Ext2 - not set


Вопрос номер раз - при создании дочернего класса (переменная $Ext) в этой переменной будет содержаться "ссылка" на родительский класс (причем с дефолтными значениями свойств) или еще один экземпляр класса Engine?

Вопрос номер два - как обратиться к свойствам "sibling" класса из соседнего? Например нужно взять значение свойства из класса Ext в классе Ext2?

Спасибо!



Спустя 14 минут, 44 секунды (15.06.2009 - 20:32) vasa_c написал(а):
В переменной будет содержаться ссылка на свой тип (т.е. класс). А у класса будет ссылка на родительский (смысл тот, какие там ссылки в реализации PHP, хз).

"нужно взять значение свойства из класса Ext в классе Ext2" или всё же, взять значение из объекта класса Ext в методе объекта класса Ext2?
Если второе, как обычно: $objectClassaExt->svoystvo. + будут влиять модификаторы доступа.

Спустя 10 минут, 23 секунды (15.06.2009 - 20:42) glock18 написал(а):
1. Насколько я знаю, ни то ни другое. Фактически при наследовании создается новый класс, который получает свойства и методы родителя с модификатороми protected и public.

По свойствам это несколько ближе к
Цитата
еще один экземпляр класса Engine

поскольку
PHP
echo ($Ext instanceof Engine);

выведет 1 (или true).

То есть фактически в какой-то степени Ext до сих пор является объектом класса Engine.

Соответственно, при создании объекта оператором new, у тебя в переменной будет не ссылка, а новый объект. Это прекрасно иллюстрирует твой первый echo:
PHP
$Ext->set1('test');
$Engine->show();

Цитата
Engine - not set


2. Не знаю насколько это в пределах ООП. По-моему, это совершенно не нужно и невозможно в ООП.

Спустя 1 минута, 11 секунд (15.06.2009 - 20:44) kirik написал(а):
Спасибо за ответ!
С первым все ясно.

Цитата (vasa_c @ 15.06.2009 - 12:32)
или всё же, взять значение из объекта класса Ext в методе объекта класса Ext2?

Так точно!

Цитата (vasa_c @ 15.06.2009 - 12:32)
как обычно: $objectClassaExt->svoystvo

тоесть эта переменная $objectClassaExt должна быть глобальной (или определенной как global в вызываемом методе объекта)? (чтобы она была доступна в методе объекта класса Ext2). Грубо говоря нужно использовать ту же "ссылку" что при вызове на прямую, что при вызове из какого-либо метода. Тоесть системы неких внутренних обращений в родительском классе между дочерними нет?

Спустя 1 минута, 34 секунды (15.06.2009 - 20:45) glock18 написал(а):
Цитата
Тоесть системы неких внутренних обращений в родительском классе между дочерними нет?


Нет.

Спустя 1 минута, 24 секунды (15.06.2009 - 20:47) kirik написал(а):
Цитата (glock18 @ 15.06.2009 - 12:42)
Соответственно, при создании объекта оператором new, у тебя в переменной будет не ссылка, а новый объект.

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

Спустя 1 минута, 2 секунды (15.06.2009 - 20:48) kirik написал(а):
Цитата (glock18 @ 15.06.2009 - 12:45)
Нет.

Понятно, спасибо! smile.gif

Спустя 1 минута, 13 секунд (15.06.2009 - 20:49) glock18 написал(а):
Цитата (kirik @ 15.06.2009 - 17:47)
Выходит если у меня 20 дочерних классов вызывают имеют один и тот же родительский, то создатся 20 родительских? Это ведь очень ресурсоемко получается (память съедается)...


Конечно. Создание каждого объекта - выделение ему своей памяти.

Спустя 43 секунды (15.06.2009 - 20:50) glock18 написал(а):
Цитата (kirik @ 15.06.2009 - 17:48)
Понятно, спасибо!

Пожалуйста smile.gif

Спустя 5 минут, 26 секунд (15.06.2009 - 20:55) Sylex написал(а):
Цитата (kirik @ 15.06.2009 - 23:44)
тоесть эта переменная $objectClassaExt должна быть глобальной (или определенной как global в вызываемом методе объекта)? (чтобы она была доступна в методе объекта класса Ext2). Грубо говоря нужно использовать ту же "ссылку" что при вызове на прямую, что при вызове из какого-либо метода. Тоесть системы неких внутренних обращений в родительском классе между дочерними нет?

нету, да и вряд ли они нужны вообще где-то, по логике smile.gif

Спустя 33 минуты, 51 секунда (15.06.2009 - 21:29) sergeiss написал(а):
Цитата (kirik @ 15.06.2009 - 21:17)
Вопрос номер два - как обратиться к свойствам "sibling" класса из соседнего? Например нужно взять значение свойства из класса Ext в классе Ext2?
PHP
// определяем класс Ext2
Class Ext2 extends Engine 
{
  function show2()
  {
  echo "\nExt2 - ".$this->variable;
  }
  function show3( $v ) // здесь $v будет экземпляр класса Ext
  {
  echo "\nExt in Ext2 - ".$v->variable;
  }
}
// и вызываем:
$Engine = New Engine;
$Ext = New Ext;
$Ext2 = New Ext2;

$Ext->set1('test');
$Ext2->show3($Ext);


То есть, обращаемся к "соседнему" классу, родственному, вобщем-то, просто через представителя этого класса, т.е. через переменную с типом Ext.

Или я что-то не так понял???

Спустя 1 час, 35 минут, 1 секунда (15.06.2009 - 23:04) kirik написал(а):
sergeiss
не, все правильно.

Спустя 10 минут, 20 секунд (15.06.2009 - 23:14) kirik написал(а):
Еще один вопрос..
Насколько правильно будет сделать так:
Свернутый текст
PHP
Class Engine {
    function set($var)
    {
        Ext1::$instance->variable = $var;
    }
}

Class Ext1 extends Engine {
    static public $instance = null;
    public $variable = 'not set';

    static public function instanceGet()
    {
        if(empty(self::$instance))
        {
            self::$instance = New self();
        }
        return self::$instance;
    }

    function show1()
    {
        echo "\nExt - ".$this->variable;
    }
}

Class Ext2 extends Engine {
    static public $instance = null;

    static public function instanceGet()
    {
        if(empty(self::$instance))
        {
            self::$instance = New self();
        }
        return self::$instance;
    }

    function show2()
    {
        echo "\nExt2 - ".Ext1::$instance->variable;
    }
}

$Engine = New Engine;

Ext1::instanceGet();
Ext2::instanceGet();

$Engine->set('test1');

Ext1::$instance->show1();
Ext2::$instance->show2();


Поясню, такая заморочка на мой взгляд довольно удобна тем, что мы имеем доступ к любому дочернему классу отовсюду (через статичное свойство $instance каждого дочернего класса).

Спустя 8 минут, 5 секунд (15.06.2009 - 23:22) sergeiss написал(а):
А какая у тебя вообще конечная цель, зачем это всё нужно - вот это вот обращение к "сестриным" smile.gif классам?

Спустя 6 минут, 58 секунд (15.06.2009 - 23:29) kirik написал(а):
Допустим есть основной класс (Engine), к которому "прикрепляются" дочерние. Допустим дочерний класс работы с новостями (News) и дочерний класс работы с БД (Db). В классе работы с новостями можно будет просто написать Db::$instance->method(); для вызова какого-либо метода класса Db. Чтобы не создавать кучу глобальных переменных или не заботиться о том, прописал-ли ты их в строчку global..

Спустя 24 минуты, 52 секунды (15.06.2009 - 23:54) sergeiss написал(а):
Ежели тебе так хочется... Правда, какая-то (на мой взгляд) странная организация данных будет smile.gif
Но - ежели хочется, пусть бы даже просто в учебных целях, то почему бы не сделать проще: сначала создать экземпляры каждого типа, а после инициализации передать все "сестринские" классы по ссылке? И делай дальше всё, что хочешь.
Например, есть у тебя основной класс Engine и дочерние EngineNews, EngineDB, EngineBrain.
Дальше я не буду писать код (только минимум), дабы не накосячить smile.gif А только саму суть, алгоритм.
1. Объявляешь описание класса Engine, со всеми его переменными и функциями.
2. Объявляешь описание всех дочерних классов. И у каждого из них делаешь очень интересные переменные. Например, в классе EngineNews:
PHP
class EngineNews ....
{
  var 
$refEngineDB;
  var 
$refEngineBrain;
  ... 
// constructor

  
function setsisters( &$DB, &$Brain )
  {
    
$this->refEngineDB=$DB;
    
$this->refEngineBrain=$Brain;
  }
}

$EngNews=new EngineNews;
$EngDB=new EngineDB;
$EngBrain=new EngineBrain;

// а вот далее делаем интересные назначения
$EngNews->setsisters$EngDB$EngBrain);


мы передаем значения по ссылке, поэтому внутри класса EngineNews будут не копии, а прямое обращение к сёстрам, $DB и $Brain внутри класса EngineNews будут напрямую обращаться к другим классам.
То есть, любые изменения в переменных $EngDB и $EngBrain будут автоматически учитываться в переменных $DB и $Brain, находящихся в экземпляре класса $EngineNew с именем $EngNews.

Не знаю, понятно ли я объяснил свою мысль smile.gif Но работать это будет "как часы". Ежели непонятно, то я сделаю примерчик. С утра wink.gif

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

Спустя 13 минут, 14 секунд (16.06.2009 - 00:07) glock18 написал(а):
Цитата (kirik @ 15.06.2009 - 20:14)
Еще один вопрос..
Насколько правильно будет сделать так:
Свернутый текст
PHP
Class Engine {
    function set($var)
    {
        Ext1::$instance->variable = $var;
    }
}

Class Ext1 extends Engine {
    static public $instance = null;
    public $variable = 'not set';

    static public function instanceGet()
    {
        if(empty(self::$instance))
        {
            self::$instance = New self();
        }
        return self::$instance;
    }

    function show1()
    {
        echo "\nExt - ".$this->variable;
    }
}

Class Ext2 extends Engine {
    static public $instance = null;

    static public function instanceGet()
    {
        if(empty(self::$instance))
        {
            self::$instance = New self();
        }
        return self::$instance;
    }

    function show2()
    {
        echo "\nExt2 - ".Ext1::$instance->variable;
    }
}

$Engine = New Engine;

Ext1::instanceGet();
Ext2::instanceGet();

$Engine->set('test1');

Ext1::$instance->show1();
Ext2::$instance->show2();


Поясню, такая заморочка на мой взгляд довольно удобна тем, что мы имеем доступ к любому дочернему классу отовсюду (через статичное свойство $instance каждого дочернего класса).

По-моему, это достаточно интересно. Это паттерн singleton - вполне имеет место быть в некоторых случаях. Правда в части случаев он может быть полностью перекрыт static методами и свойствами класса.

Довольно интересная реализация.

Спустя 2 минуты, 28 секунд (16.06.2009 - 00:10) kirik написал(а):
Цитата (sergeiss @ 15.06.2009 - 15:54)
Ежели непонятно, то я сделаю примерчик.

Спасибо! Все очень понятно! smile.gif
Тогда, при таком подходе, если появится новый класс, то тогда нужно будет прописывать еще одну реферальную переменную и добавлять значение в метод setsisters(). Впринципе ничего страшного, но если у нас этот класс будет подключаться/вызываться после того, как мы вызвали setsisters(), тогда нужно будет придумывать еще какой-то метод.. Хотя можно что-нибудь придумать через переменные переменные..

"Зарядка для хвоста" не помешает smile.gif

Спустя 7 минут, 18 секунд (16.06.2009 - 00:17) sergeiss написал(а):
Цитата (kirik @ 16.06.2009 - 01:10)
Хотя можно что-нибудь придумать через переменные переменные..

А зачем? Просто передаешь 2 параметра: один - ссылка на объект нужного класса, другой - некий индекс (число, строка - что угодно). Так внутри анализируешь и назначаешь в ту или иную внутреннюю переменную.

Спустя 13 минут, 26 секунд (16.06.2009 - 00:31) kirik написал(а):
Цитата (glock18 @ 15.06.2009 - 16:07)
Это паттерн singleton

О, круто! smile.gif Теперь хоть название знаю. Тоесть на практике singleton и определение свойства в родительском классе, содержащим ссылку на дочерний не особо различаются?

Спустя 2 часа, 4 минуты, 12 секунд (16.06.2009 - 02:35) Alchemist написал(а):
kirik, я все еще плохо понимаю, зачем тебе это нужно, но в любом случае, мне кажется, что ты идешь по неправильному пути. Принцип дописывания родительского класса при создании нового дочернего, или содержания ссылок на на дочерние классы - в корне подрывает саму идею наследования.

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

Конечно, можно придумать как это обойти, особенно если использовать статические классы, например можно передавать папе указатель на нужную функцию при инициализации класса. И уж тем более это можно сделать в пхп4-5, который в буквальном смысле позволяет "писать мелом на стене"... Но, ИМХО, это уже не будет ООП в классическом понимании.

Спустя 2 часа, 2 минуты, 46 секунд (16.06.2009 - 04:38) kirik написал(а):
Alchemist
Спасибо за объяснение! Да, ты верно сказал, скорее всего я пытаюсь что-то выдумать не вникнув окончательно в логику ООП. Сейчас просто сижу разбираю готовые wordpress и cakephp, смотрю как у них это все работает, и они там не особо используют синглтоны..

Спустя 1 час, 10 минут, 38 секунд (16.06.2009 - 05:48) Sylex написал(а):
kirik
синглтон часто используют, а на счет того что где как и лучше - спорить не буду smile.gif

почитай

Порождающие шаблоны проектирования

Singleton


Спустя 2 часа, 46 минут, 49 секунд (16.06.2009 - 08:35) glock18 написал(а):
Цитата (kirik @ 15.06.2009 - 21:31)
Тоесть на практике singleton и определение свойства в родительском классе, содержащим ссылку на дочерний не особо различаются?


Не совсем то) В твоем случае -
PHP
static public $instance null;
и есть синлтон. Sylex дал ссылочку с описанием как раз.

А синглтоны очень много используют.

Цитата
Сейчас просто сижу разбираю готовые wordpress и cakephp

Могу посоветовать посмотреть Yii. По-моему, написан очень грамотно. На чистом php5 с присущими ему фишечками. И сам по себе фреймворк в сравнении с другими очень хороший. Я его смотрел - чисто в познавательных целях очень подходящая цель.

Спустя 3 часа, 53 минуты, 3 секунды (16.06.2009 - 12:28) sergeiss написал(а):
kirik - ну и к чему пришел в итоге?

Спустя 5 часов, 9 минут, 1 секунда (16.06.2009 - 17:37) kirik написал(а):
Цитата (glock18 @ 16.06.2009 - 00:35)
Могу посоветовать посмотреть Yii.

Спасибо! Скачал ужо smile.gif

Цитата (sergeiss @ 16.06.2009 - 04:28)
kirik - ну и к чему пришел в итоге?

Пока я пришел к абсолютно запутанным мыслям в голове smile.gif Немного нужно разобрать все по полкам.. Как уложу все прочитанное и узнанное во что-нибудь более вменяемое, приду просить советов smile.gif

Спустя 13 минут, 29 секунд (16.06.2009 - 17:51) Sylex написал(а):
kirik
Это хорошо! smile.gif Непредубежденность ни в чем и пылкий ум - приведут к Истине smile.gif

Спустя 4 часа, 3 минуты, 27 секунд (16.06.2009 - 21:54) sergeiss написал(а):
Цитата (kirik @ 16.06.2009 - 18:37)
Пока я пришел к абсолютно запутанным мыслям в голове. Немного нужно разобрать все по полкам.. Как уложу все прочитанное и узнанное во что-нибудь более вменяемое, приду просить советов

Я вот что подумал... Ты хотел С++ заниматься? Так вот там - одни сплошные классы smile.gif А в ПХП - упрощенный вариант. Поняв там - лучше поймешь тут.

Например. Форма для данных, проще говоря - одно стандартное окно. Образовано на основе целой серии классов. 2 разных окна - "дочки" одного и того же класса, имеющие своих элементы, как визуальные, так и невизуальные. Всякие окна ввода, чекбоксы и т.д. - они тоже на классах построены. И даже более того - чекбокс, окно ввода, радиокнопка, форма - они все имеют какого-то общего предка где-то в 3-м или 4-м колене.
И обратиться там легко и просто к разным частям одного окна из другого, также как и к любым (публичным) свойствам любых других объектов (представителей тех или иных классов) . Но именно как я уже описывал - все реальные связи, по сути дела, прописываются уже в момент исполнения программы, когда представители этих классов уже созданы.

Спустя 8 минут, 20 секунд (16.06.2009 - 22:02) glock18 написал(а):
Цитата (sergeiss @ 16.06.2009 - 18:54)
Я вот что подумал... Ты хотел С++ заниматься? Так вот там - одни сплошные классы smile.gif А в ПХП - упрощенный вариант. Поняв там - лучше поймешь тут.

+1000

Спустя 1 час, 34 минуты, 12 секунд (16.06.2009 - 23:37) kirik написал(а):
Цитата (sergeiss @ 16.06.2009 - 13:54)
Ты хотел С++ заниматься? Так вот там - одни сплошные классы

Именно по этому я решил сначала разобраться с классами в php, а потом учить C++ smile.gif

Спустя 8 часов, 9 минут, 41 секунда (17.06.2009 - 07:46) sergeiss написал(а):
Цитата (kirik @ 17.06.2009 - 00:37)
Именно поэтому я решил сначала разобраться с классами в php, а потом учить C++

Э... Я имел ввиду как раз прямо противоположное smile.gif Ну, или хотя бы в параллель: классы в ПХП и С++. Потому что в С++ у тебя вариантов других нету, кроме как разбираться и активно работать с классами.
Хотя, конечно, это моё личное мнение, та самая ИМХА, которую "хрен оспоришь" wink.gif

Спустя 9 часов, 11 минут, 4 секунды (17.06.2009 - 16:57) kirik написал(а):
Цитата (sergeiss @ 16.06.2009 - 23:46)
Ну, или хотя бы в параллель

Просто C++ я изучаю пока для себя, а вот php может помочь в разработке, поэтому сначала думаю с php разобраться, а потом с C++ немного попроще будет smile.gif
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.