Поясните некоторую особенность работы с классами

hohoho

Новичок
Поясните некоторую особенность работы с классами

В общем проблема такая, точнее не проблема, а хотелось бы что бы было так:
Создаётся экземпляр класса, который в зависимости от некоторых условий создаёт какой-либо класс, который является его потомком (в нём могут быть переопределённые методы родительского класса ) и возвращает экземпляр класса потомка.
Для проверки работоспособности такой конструкции я написал примерно следующее:
PHP:
<?php

class parent
{
        function parent() {
                $child = new child;
                return $child;
        }

        function parent_method() {
                echo "Метод родительского класса parent, parent_method()<br />\n";
        }

        function parent_method_mod() {
                echo "Метод родительского класса parent, parent_method_mod()<br />\n";
        }
}

class child extends parent
{
        function child() {
                // some code
        }

        function child_method() {
                echo "Метод дочернего класса child, child_method()<br />\n";
        }

        function parent_method_mod() {
                echo "Переопределённый метод родительского класса parent, parent_method_mod()<br />\n";
        }
}

$class = new parent;
$class->parent_method();
$class->child_method();
$class->parent_method_mod();
?>
Но это всё счастье, естественно не работает. Кому не лень объясните почему, и как можно реализовать подобную конструкцию хотя бы в двух словах. Просто мне даже интересно.
 

senich

Новичок
хммм а почему экземпляр класса парент будет Тебе исполнять методы класса чайлд?
 

Кром

Новичок
>Создаётся экземпляр класса, который в зависимости от некоторых условий создаёт какой-либо класс, который является его потомком

В контексте приведенного тобой когда эту фразу невозможно понять.
 

svetasmirnova

маленький монстрик
function parent() {
$child = new child;
return $child;
}
Конструктор ничего не возвращает. Никогда. Он создаёт экземпляр класса. Того, в котором определён. По другому не бывает, извини.
 

AnToXa

prodigy-одаренный ребенок
Конструктор ничего не возвращает. Никогда. Он создаёт экземпляр класса. Того, в котором определён. По другому не бывает, извини.
а можно я позанудствую? :) а что такое "конструктор создает"?
 

svetasmirnova

маленький монстрик
AnToXa
Правильно занудствуешь :) Формулировки нужно точные подбирать.
PHP 5 позволяет объявлять методы-конструкторы. Классы, в которых объявлен метод-констуктор, будут вызывать этот метод при каждом создании нового объекта, так что это может оказаться полезным, чтобы, например, инициализировать какое-либо состояние объекта перед его использованием.
Это из мануала PHP.
И wikipedia ещё: http://en.wikipedia.org/wiki/Constructor_(computer_science)

Тем более, что при желании можно в конструкторе выкинуть Exception, что расходится с моей предпосылкой:
>Конструктор ничего не возвращает. Никогда.
:)

hohoho
не слушай зануд, слушай Profic
 

whirlwind

TDD infected, paranoid
> хммм а почему экземпляр класса парент будет Тебе исполнять методы класса чайлд?

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

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

hohoho

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

svetasmirnova

маленький монстрик
whirlwind
>В php нет понятия абстрактного класса
Почему вы так уверены?
>pure-virtual
А это где? В PHP?
 

whirlwind

TDD infected, paranoid
>Почему вы так уверены

Потому что pure-virtual это

virtual abstractMethod() = NULL;

в прототипе класса.

PS. Т.е. место под указатель на метод резервируется, но не определяется. Нельзя создать экземпляр абстрактного класса, можно лишь сослаться на объявленное интерфейсом до объявления наследника.

-~{}~ 07.12.05 14:18:

>>pure-virtual
>А это где? В PHP?

Это в ООП, рядом с полиморфизмом
 

svetasmirnova

маленький монстрик
в прототипе класса.

PS. Т.е. место под указатель на метод резервируется, но не определяется. Нельзя создать экземпляр абстрактного класса, можно лишь сослаться на объявленное интерфейсом до объявления наследника.
Я в курсе, а Вы, похоже, нет: http://www.php.net/manual/en/language.oop5.abstract.php
>Это в ООП, рядом с полиморфизмом
А я думала в С++
 

Profic

just Profic (PHP5 BetaTeam)
В php5 тоже есть как интерфейсы, так и абстрактные методы/классы. И все методы в php "виртуальные". В кавычках потому как преобразовать объект дочернего класса в объект родительского в php нельзя.
PHP:
<?php 

class grand { 
	function grand() {} 

	function parent_method() { 
		echo "Метод родительского класса parent, parent_method()<br />\n"; 
	} 

	function parent_method_mod() { 
		echo "Метод родительского класса parent, parent_method_mod()<br />\n"; 
	} 
} 

class child extends grand { 
	function child() { 
		// some code 
	} 

	function child_method() { 
		echo "Метод дочернего класса child, child_method()<br />\n"; 
	} 

	function parent_method_mod() { 
		echo "Переопределённый метод родительского класса parent, parent_method_mod()<br />\n"; 
	} 
} 

function job(grand $o) {
	$o->parent_method(); 
	$o->child_method(); 
	$o->parent_method_mod(); 
}

$o = new child; 
job($o);

?>
Кстати php 5.1 на имя класса parent матюкается :)
 

AnToXa

prodigy-одаренный ребенок
whirlwind
1. в php нет ключевого слова virtual.
2. в php нет такой штуки как NULL в смысле C++, т.к. вообще нет указателей.
3. в php нет такого синтаксиса объявления функций.
4. в php, если я не ошибаюсь, вообще невозможно и не нужно делать forward declarations.
5. pure virtual - это термин языка C++, и, возможно, каких-то еще, в других языках используются другие термины, например deferred function.
6. pure virtual вообще никакого отношения к определению oop не имеет, первоначальное определение алана кея говорит примерно следующее:
- есть только объекты
- объекты общаются посредством посылки сообщений
- нет никаких других средств общения

полиморфизм, наследование и проч - это механизмы и, отчасти, естественные следствия определения, а не определение ООП.
 

whirlwind

TDD infected, paranoid
svetasmirnova

>Я в курсе, а Вы, похоже, нет: http://www.php.net/manual/en/language.oop5.abstract.php

Признаюсь, не читал. Спасибо.

AnToXa Я прекрасно знаю чего нет в php.
Не важно pure-virtual или еще как то, смысл в том, что абстрактный класс не используется для конструкции объектов - иначе говоря делает класс абстрактным, фактически не существующим. И при чем здесь Кей, если рассматривается частный случай?

> в php, если я не ошибаюсь, вообще невозможно и не нужно делать forward declarations.

Да ну?! А с наборы однотипных объектов Вы каким способом инкапсулируете?
 

AnToXa

prodigy-одаренный ребенок
> в php, если я не ошибаюсь, вообще невозможно и не нужно делать forward declarations.

Да ну?! А с наборы однотипных объектов Вы каким способом инкапсулируете?
наборы - это наборы, причем тут инкапсуляция, наверное я не понял вопрос.
 

whirlwind

TDD infected, paranoid
кк. на пальцах

PHP:
class constraint{
    private $cv;
    public function getVal() { return $this->cv; }
    public function validate($v){ return false; }
}

class maxval extends constraint{
   public function validate($v){ return $v>$this->getVal() ? false : true; }
}

class minlen extends constraint{
   public function validate($v){ return $v<$this->getVal() ? false : true; }
}

class atom{
   private $constraints;

   public function setConstraint($n,$o){
       if ( is_a($o,"constraint") ){
          return false;
       }
        $this->constraints[$n] = $o;
   }

   public function validate($v){
      foreach ( array_keys($this->constraints) as $key ){
        if ( !$this->_check($key)->validate($v) ){
           return false;
        }
      }
       return true;
   }
}

class IntAtom extends atom{
    IntAtom(){
         $this->setConstraint('minval',new minval(1024));
         ....
    }

}
По моему все прозрачно и прекрасно рефакторится. Как бы выглядел код без constraint и atom, я ч.г. затрудняюсь представить.

-~{}~ 07.12.05 15:48:

AnToXa ИМХО это Вы, кажется, не отличаете ООП от особеностей CPP. forward declaration не имеют никакого смысла в _не_компиляторах_. Вы бы еще про extrn вспомнили.
 

AnToXa

prodigy-одаренный ребенок
whirlwind
определение кея вообще мало имеет общего с C++, оно очень к smalltalk близко скорее, так что не в кассу ваши размышления чего я там путаю.

насчет компиляторов - это спорный вопрос, смотря что считать компилятором. вот ява та же, компилятор многопроходной никаких forward decls.
 

whirlwind

TDD infected, paranoid
>вот ява та же, компилятор многопроходной никаких forward decls

И правильно что нету, не нужен он абсолютно - такой же геммор как и goto. Я и нигде не говорил, что fd - это обязательный атрибут компилируемого языка, так что никакого спорного вопроса. Просто я сначала недопер про какой Вы forward declaration речь ведете. fd трактуется как предварительное объявление, что вообщем то и имеем в контексте обсуждения абстрактных классов.
 
Сверху