class test {
function __construct() {
echo __CLASS__;
}
}
class demo extends test {
}
new demo;
выводит TEST, почему? как заставить, чтобы выводило DEMO?
Спустя 9 минут, 1 секунда (3.07.2010 - 01:00) Medkop написал(а):
понял как get_class
Спустя 3 дня, 2 часа, 14 минут, 31 секунда (6.07.2010 - 03:14) Medkop написал(а):
делаю сингл тон
выводит ошибку, т.к. абстрактный класс создавать нельзя, как получить название класса???
abstract class base
{
private function __construct(){}
private static $__instance = null;
static function create()
{
if (self::$__instance)
return;
self::$__instance = new [b]__CLASS__[/b];
}
}
class test extends base
{
}
test::create();
выводит ошибку, т.к. абстрактный класс создавать нельзя, как получить название класса???
Спустя 4 часа, 41 минута, 24 секунды (6.07.2010 - 07:55) linker написал(а):
В данном случае абстракция - лишнее, класс в котором нет абстрактных методов, не должен быть абстрактным. Второе, статические поля, методы класса принадлежат классу в котором они объявлены. Третье, приватные поля и методы не наследуются. Исходя из мною сказанного, подумайте и перепишите как положено.
Спустя 8 минут, 29 секунд (6.07.2010 - 08:04) glock18 написал(а):
позднее статическое связывание
http://php.net/manual/en/language.oop5.lat...ic-bindings.php
есть начиная с 5.3. никак по-человечески получить в статическом методе имя класса из которого он вызван в <5.3 нельзя. (debug_backtrace и прочие извращение - не по-человечески).
если не хочешь или не можешь ставить 5.3, то лучше избавляйся от статичности.
тем не менее, есть один хук для этого случая.
делается оно примерно так:
в каждом потомке будут такие три строчки. не слишком изящно, но бывает хуже. не нравится это - читай выше.
http://php.net/manual/en/language.oop5.lat...ic-bindings.php
есть начиная с 5.3. никак по-человечески получить в статическом методе имя класса из которого он вызван в <5.3 нельзя. (debug_backtrace и прочие извращение - не по-человечески).
если не хочешь или не можешь ставить 5.3, то лучше избавляйся от статичности.
тем не менее, есть один хук для этого случая.
делается оно примерно так:
abstract class base
{
private function __construct(){}
private static $__instance = null;
static function create($className = __CLASS__)
{
if (self::$__instance)
return;
self::$__instance = new $className;
}
}
class test extends base
{
static function create($className = __CLASS__)
{
return parent::create($className);
}
}
test::create();
в каждом потомке будут такие три строчки. не слишком изящно, но бывает хуже. не нравится это - читай выше.
Спустя 15 часов, 11 минут, 11 секунд (6.07.2010 - 23:15) Medkop написал(а):
Цитата (linker @ 6.07.2010 - 04:55) |
В данном случае абстракция - лишнее, класс в котором нет абстрактных методов, не должен быть абстрактным. Второе, статические поля, методы класса принадлежат классу в котором они объявлены. Третье, приватные поля и методы не наследуются. Исходя из мною сказанного, подумайте и перепишите как положено. |
Во многих языках допустимо объявить любой класс абстрактным, даже если в нём нет абстрактных методов, именно для запрещения создания экземпляров. Абстрактный класс можно рассматривать в качестве интерфейса к семейству классов, порождённому им, но, в отличие от классического интерфейса, абстрактный класс может иметь определённые методы, а также свойства.
Спустя 32 минуты, 19 секунд (6.07.2010 - 23:47) Medkop написал(а):
Цитата (glock18 @ 6.07.2010 - 05:04) |
позднее статическое связывание http://php.net/manual/en/language.oop5.lat...ic-bindings.php есть начиная с 5.3. никак по-человечески получить в статическом методе имя класса из которого он вызван в <5.3 нельзя. |
http://php.net/manual/en/language.oop5.lat...ic-bindings.php, прочитал, спасибо! но не на много код изменится, от ниже описанного, там будут другие три строчки
abstract class base
{
private function __construct(){}
private static $__instance = null;
static function get_class(){}
static function create()
{
if (self::$__instance)
return;
self::$__instance = new static::get_class();
}
}
class test extends base
{
static function get_class()
{
return __CLASS__;
}
}
test::create();
хотелось сделать этот момент прозрачным ..
Спустя 7 часов, 50 минут, 34 секунды (7.07.2010 - 07:38) linker написал(а):
Цитата (Medkop @ 6.07.2010 - 20:15) |
Во многих языках допустимо объявить любой класс абстрактным, даже если в нём нет абстрактных методов, именно для запрещения создания экземпляров. Абстрактный класс можно рассматривать в качестве интерфейса к семейству классов, порождённому им, но, в отличие от классического интерфейса, абстрактный класс может иметь определённые методы, а также свойства. |
Medkop, это дурнейший тон.
Для того, чтобы нельзя было создавать экземпляры класса, достаточно объявить конструктор приватным.
Вы путаете изначально сами понятия "абстрактный класс" и "интерфейс", потому и ошибки такие.
Это не валидно
self::$__instance = new static::get_class();.
Спустя 59 минут, 29 секунд (7.07.2010 - 08:38) Medkop написал(а):
из приведенного примера видно, что класс создать можно, исп. стат. функцию create, поэтому был взят абстрактный класс
Спустя 26 минут, 52 секунды (7.07.2010 - 09:04) linker написал(а):
Ну обзовите его просто class base {}, не нужно здесь абстракций (не засоряйте код и не черните чистое имя ООП), а конструктор у вас полюбас приватный, значит $object = new base(); не сработает. Зато замечательно сработает $object = new test(); без всяких там test::create();
Спустя 1 час, 42 минуты, 34 секунды (7.07.2010 - 10:47) glock18 написал(а):
Medkop
для 5.3 вообще не надо лишних строк
self::$__instance = new get_called_class();
и не нужен никакой get_class
linker
то есть по-твоему запрещать создание класса делая конструктор приватным это нормально?
вообще ситуация такая, что делать абстрактным его смысла особого нет, поскольку методов нет абстрактных. но приватный конструктор просто делает невозможным создание объекта извне. Может по логике он и должен быть абстрактным, но стоит все таки делать такое ограничение, когда есть веские основания типа абстрактных методов.
ЗЫ: считаю, что если сильно хочется запретить, то лучше делать абстрактным, чем приватить конструктор. каким образом это расходится с ооп?
для 5.3 вообще не надо лишних строк
self::$__instance = new get_called_class();
и не нужен никакой get_class
linker
то есть по-твоему запрещать создание класса делая конструктор приватным это нормально?
вообще ситуация такая, что делать абстрактным его смысла особого нет, поскольку методов нет абстрактных. но приватный конструктор просто делает невозможным создание объекта извне. Может по логике он и должен быть абстрактным, но стоит все таки делать такое ограничение, когда есть веские основания типа абстрактных методов.
ЗЫ: считаю, что если сильно хочется запретить, то лучше делать абстрактным, чем приватить конструктор. каким образом это расходится с ооп?
Спустя 21 минута, 41 секунда (7.07.2010 - 11:09) linker написал(а):
glock18, приватный конструктор - это нормально. Делать класс абстрактным ради того, чтобы нельзя было создать экземпляр такого класса - бред. Абстракция существует не для этого (еще раз прощу не портить честное имя ООП). И вообще в данном примере не сингтон, ибо можно сделать $object = new test(); а в сути сингтонов так делать нельзя. Суть синглтонов в том, чтобы гарантировать единственность объекта определенного класса. В данном примере оно не выполняется. Классический случай сингтона
class MyClassи еще, вот так
{
private static $_instance = null;
private function __construct() {}
public static function create()
{
if (is_null(self::$_instance)) self::$_instance = new MyClass;
return self::$_instance;
}
}
self::$__instance = new get_called_class();невалидно, правильно только
$object = new MyClass();
или
$object = new $ClassName();
Спустя 52 минуты, 46 секунд (7.07.2010 - 12:01) glock18 написал(а):
linker
конструктов листинге выше приватный, так что синглтон в этом плане корректен, хотя создать два объекта все равно можно. Но про __clone вы тоже ничего не сказали.
Я не порочу имя ООП и понимаю для чего абстрактные классы вообще нужны. Но фактически в данном случае это такое же нестандартное использование этой возможности, как и использование приватности конструктора. Не вижу, чем принципиально приватность лучше. Очевидно, что данный случай не выражает то, как надо использовать абстрактность, и используется она здесь неэффективно по сравнению с тем, как, например, в паттерне стратегия.
ну да, надо в переменную сначала имя положить. думаю, человек догадается )
конструктов листинге выше приватный, так что синглтон в этом плане корректен, хотя создать два объекта все равно можно. Но про __clone вы тоже ничего не сказали.
Я не порочу имя ООП и понимаю для чего абстрактные классы вообще нужны. Но фактически в данном случае это такое же нестандартное использование этой возможности, как и использование приватности конструктора. Не вижу, чем принципиально приватность лучше. Очевидно, что данный случай не выражает то, как надо использовать абстрактность, и используется она здесь неэффективно по сравнению с тем, как, например, в паттерне стратегия.
self::$__instance = new get_called_class();
ну да, надо в переменную сначала имя положить. думаю, человек догадается )
Спустя 26 минут, 22 секунды (7.07.2010 - 12:28) linker написал(а):
glock18, к сожалению приватные методы и поля класса не наследуются дочерними классами, а значит по-умолчанию класс test имеет конструктор public, а значит $object = new test(); сработает, в синглтоне такого быть не может в принципе.
__clone - само собой в приват.
Синглтон из класса base вообще никакой, указание abstract перечеркивает напрочь возможность создания экземпляра данного класса, хотя для этого достаточно стандартного решения с приватным конструктором.
Плюс, пытаясь предугадать логику ТС, который обозначил класс абстрактным и дал ему название base, т.е. базовый класс для других классов, могу добавить, что записав так:
__clone - само собой в приват.
Синглтон из класса base вообще никакой, указание abstract перечеркивает напрочь возможность создания экземпляра данного класса, хотя для этого достаточно стандартного решения с приватным конструктором.
Плюс, пытаясь предугадать логику ТС, который обозначил класс абстрактным и дал ему название base, т.е. базовый класс для других классов, могу добавить, что записав так:
abstract class base {...}Объект класса test2 никогда не будет создан.
class test extends base {...}
class test2 extends base {...}
test::create();
test2::create();
Спустя 1 час, 5 минут, 30 секунд (7.07.2010 - 13:33) glock18 написал(а):
кстати говоря, признаю, что поначалу не обратил внимания что речь о синглтоне. то что синглтон абстрактный и правда звучит дико. Насчет приватности тоже все верно, ну да ведь есть протектед на такие случае.
Цитата (linker @ 7.07.2010 - 09:28) |
Объект класса test2 никогда не будет создан. |
да, вернется первый объект.
вообще название create меня поначалу сбило, оно подходит больше для фабрики, а не для синглтон-аксессора.
Спустя 19 минут, 38 секунд (7.07.2010 - 13:53) linker написал(а):
Скорее всего ТС имел ввиду это
class baseТут одновременно и фабрика классов и синглтон для каждого класса.
{
protected function __construct() {}
protected function __clone() {}
public static function create()
{
if (is_null(static::$_instance))
{
$ClassName = get_called_class();
static::$_instance = new $ClassName();
}
}
}
class test extends base
{
private static $_instance = null;
}
Спустя 4 минуты, 58 секунд (7.07.2010 - 13:58) glock18 написал(а):
да, скорее всего именно это ему и надо.
ЗЫ: неужели никаких ограничений на версию и можно юзать 5.3? ))) вот это да.
ЗЫ: неужели никаких ограничений на версию и можно юзать 5.3? ))) вот это да.