Jak stworzyć klasę Singleton za pomocą klas PHP5?
Jak stworzyć klasę Singleton za pomocą klas PHP5?
Odpowiedzi:
/**
* Singleton class
*
*/
final class UserFactory
{
/**
* Call this method to get singleton
*
* @return UserFactory
*/
public static function Instance()
{
static $inst = null;
if ($inst === null) {
$inst = new UserFactory();
}
return $inst;
}
/**
* Private ctor so nobody else can instantiate it
*
*/
private function __construct()
{
}
}
Używać:
$fact = UserFactory::Instance();
$fact2 = UserFactory::Instance();
$fact == $fact2;
Ale:
$fact = new UserFactory()
Zgłasza błąd.
Zobacz http://php.net/manual/en/language.variables.scope.php#language.variables.scope.static, aby zrozumieć zakresy zmiennych statycznych i dlaczego ustawienie static $inst = null;
działa.
PHP 5.3 pozwala na tworzenie dziedzicznej klasy Singleton poprzez późne wiązanie statyczne:
class Singleton
{
protected static $instance = null;
protected function __construct()
{
//Thou shalt not construct that which is unconstructable!
}
protected function __clone()
{
//Me not like clones! Me smash clones!
}
public static function getInstance()
{
if (!isset(static::$instance)) {
static::$instance = new static;
}
return static::$instance;
}
}
To rozwiązuje problem polegający na tym, że przed PHP 5.3 każda klasa, która rozszerzyła Singleton, produkowałaby instancję swojej klasy nadrzędnej zamiast własnej.
Teraz możesz zrobić:
class Foobar extends Singleton {};
$foo = Foobar::getInstance();
A $ foo będzie instancją Foobar zamiast instancji Singleton.
"subclass should own its own static var. check this: echo get_class(Foobar::getInstance());echo get_class(Singleton::getInstance());"
.
$instance
rezyduje w Singleton, a nie w podklasie. Po utworzeniu instancji jakiejś podklasy funkcja getInstance () zwróci tę instancję dla wszystkich podklas.
Niestety odpowiedź Inwdr nie działa, gdy istnieje wiele podklas.
Oto poprawna dziedziczna klasa podstawowa Singleton.
class Singleton
{
private static $instances = array();
protected function __construct() {}
protected function __clone() {}
public function __wakeup()
{
throw new Exception("Cannot unserialize singleton");
}
public static function getInstance()
{
$cls = get_called_class(); // late-static-bound class name
if (!isset(self::$instances[$cls])) {
self::$instances[$cls] = new static;
}
return self::$instances[$cls];
}
}
Kod testowy:
class Foo extends Singleton {}
class Bar extends Singleton {}
echo get_class(Foo::getInstance()) . "\n";
echo get_class(Bar::getInstance()) . "\n";
Prawdziwy i nowoczesny sposób na stworzenie Singleton Pattern to:
<?php
/**
* Singleton Pattern.
*
* Modern implementation.
*/
class Singleton
{
/**
* Call this method to get singleton
*/
public static function instance()
{
static $instance = false;
if( $instance === false )
{
// Late static binding (PHP 5.3+)
$instance = new static();
}
return $instance;
}
/**
* Make constructor private, so nobody can call "new Class".
*/
private function __construct() {}
/**
* Make clone magic method private, so nobody can clone instance.
*/
private function __clone() {}
/**
* Make sleep magic method private, so nobody can serialize instance.
*/
private function __sleep() {}
/**
* Make wakeup magic method private, so nobody can unserialize instance.
*/
private function __wakeup() {}
}
Więc teraz możesz go używać jak.
<?php
/**
* Database.
*
* Inherited from Singleton, so it's now got singleton behavior.
*/
class Database extends Singleton {
protected $label;
/**
* Example of that singleton is working correctly.
*/
public function setLabel($label)
{
$this->label = $label;
}
public function getLabel()
{
return $this->label;
}
}
// create first instance
$database = Database::instance();
$database->setLabel('Abraham');
echo $database->getLabel() . PHP_EOL;
// now try to create other instance as well
$other_db = Database::instance();
echo $other_db->getLabel() . PHP_EOL; // Abraham
$other_db->setLabel('Priler');
echo $database->getLabel() . PHP_EOL; // Priler
echo $other_db->getLabel() . PHP_EOL; // Priler
Jak widzisz, ta realizacja jest znacznie bardziej elastyczna.
instance
funkcji $instance
powinien być null
niefalse
Prawdopodobnie powinieneś dodać prywatną metodę __clone (), aby uniemożliwić klonowanie instancji.
private function __clone() {}
Jeśli nie podasz tej metody, możliwe staje się:
$inst1=UserFactory::Instance(); // to stick with the example provided above
$inst2=clone $inst1;
teraz $inst1
! == $inst2
- nie są już tym samym wystąpieniem.
<?php
/**
* Singleton patter in php
**/
trait SingletonTrait {
protected static $inst = null;
/**
* call this method to get instance
**/
public static function getInstance(){
if (static::$inst === null){
static::$inst = new static();
}
return static::$inst;
}
/**
* protected to prevent clonning
**/
protected function __clone(){
}
/**
* protected so no one else can instance it
**/
protected function __construct(){
}
}
używać:
/**
* example of class definitions using SingletonTrait
*/
class DBFactory {
/**
* we are adding the trait here
**/
use SingletonTrait;
/**
* This class will have a single db connection as an example
**/
protected $db;
/**
* as an example we will create a PDO connection
**/
protected function __construct(){
$this->db =
new PDO('mysql:dbname=foodb;port=3305;host=127.0.0.1','foouser','foopass');
}
}
class DBFactoryChild extends DBFactory {
/**
* we repeating the inst so that it will differentiate it
* from UserFactory singleton
**/
protected static $inst = null;
}
/**
* example of instanciating the classes
*/
$uf0 = DBFactoryChild::getInstance();
var_dump($uf0);
$uf1 = DBFactory::getInstance();
var_dump($uf1);
echo $uf0 === $uf1;
respose:
object(DBFactoryChild)#1 (0) {
}
object(DBFactory)#2 (0) {
}
Jeśli używasz PHP 5.4: cecha jest opcją, więc nie musisz marnować hierarchii dziedziczenia, aby mieć wzorzec Singleton
a także zauważ, że niezależnie od tego, czy używasz cech, czy rozszerzasz klasę Singleton, jednym luźnym celem było utworzenie singletonu klas potomnych, jeśli nie dodasz następującego wiersza kodu:
protected static $inst = null;
w klasie dziecięcej
nieoczekiwany wynik to:
object(DBFactoryChild)#1 (0) {
}
object(DBFactoryChild)#1 (0) {
}
Ta metoda wymusi singletony w każdej klasie, którą chcesz, ale musisz dodać 1 metodę do klasy, w której chcesz stworzyć singleton, a to zrobi to za ciebie.
To również przechowuje obiekty w klasie „SingleTonBase”, dzięki czemu można debugować wszystkie obiekty, które były używane w systemie przez rekursywne SingleTonBase
obiekty.
Utwórz plik o nazwie SingletonBase.php i dołącz go do katalogu głównego skryptu!
Kod jest
abstract class SingletonBase
{
private static $storage = array();
public static function Singleton($class)
{
if(in_array($class,self::$storage))
{
return self::$storage[$class];
}
return self::$storage[$class] = new $class();
}
public static function storage()
{
return self::$storage;
}
}
Następnie dla każdej klasy, która ma być singletonem, po prostu dodaj tę małą pojedynczą metodę.
public static function Singleton()
{
return SingletonBase::Singleton(get_class());
}
Oto mały przykład:
include 'libraries/SingletonBase.resource.php';
class Database
{
//Add that singleton function.
public static function Singleton()
{
return SingletonBase::Singleton(get_class());
}
public function run()
{
echo 'running...';
}
}
$Database = Database::Singleton();
$Database->run();
Możesz po prostu dodać tę funkcję singleton do dowolnej klasy, która utworzy tylko 1 instancję na klasę.
UWAGA: Zawsze powinieneś ustawić prywatność __construct, aby wyeliminować użycie nowej klasy (); instancje.
class Database{
//variable to hold db connection
private $db;
//note we used static variable,beacuse an instance cannot be used to refer this
public static $instance;
//note constructor is private so that classcannot be instantiated
private function __construct(){
//code connect to database
}
//to prevent loop hole in PHP so that the class cannot be cloned
private function __clone() {}
//used static function so that, this can be called from other classes
public static function getInstance(){
if( !(self::$instance instanceof self) ){
self::$instance = new self();
}
return self::$instance;
}
public function query($sql){
//code to run the query
}
}
Access the method getInstance using
$db = Singleton::getInstance();
$db->query();
Tak naprawdę nie musisz używać wzorca Singleton, ponieważ uważa się go za antypattern. Zasadniczo istnieje wiele powodów, aby w ogóle nie wdrażać tego wzorca. Przeczytaj to na początek: Najlepsza praktyka na lekcjach singletona PHP .
Jeśli mimo wszystko nadal uważasz, że musisz użyć wzorca Singleton, moglibyśmy napisać klasę, która pozwoli nam uzyskać funkcjonalność Singleton poprzez rozszerzenie naszej abstrakcyjnej klasy SingletonClassVendor.
Po to przyszedłem, aby rozwiązać ten problem.
<?php
namespace wl;
/**
* @author DevWL
* @dosc allows only one instance for each extending class.
* it acts a litle bit as registry from the SingletonClassVendor abstract class point of view
* but it provides a valid singleton behaviour for its children classes
* Be aware, the singleton pattern is consider to be an anti-pattern
* mostly because it can be hard to debug and it comes with some limitations.
* In most cases you do not need to use singleton pattern
* so take a longer moment to think about it before you use it.
*/
abstract class SingletonClassVendor
{
/**
* holds an single instance of the child class
*
* @var array of objects
*/
protected static $instance = [];
/**
* @desc provides a single slot to hold an instance interchanble between all child classes.
* @return object
*/
public static final function getInstance(){
$class = get_called_class(); // or get_class(new static());
if(!isset(self::$instance[$class]) || !self::$instance[$class] instanceof $class){
self::$instance[$class] = new static(); // create and instance of child class which extends Singleton super class
echo "new ". $class . PHP_EOL; // remove this line after testing
return self::$instance[$class]; // remove this line after testing
}
echo "old ". $class . PHP_EOL; // remove this line after testing
return static::$instance[$class];
}
/**
* Make constructor abstract to force protected implementation of the __constructor() method, so that nobody can call directly "new Class()".
*/
abstract protected function __construct();
/**
* Make clone magic method private, so nobody can clone instance.
*/
private function __clone() {}
/**
* Make sleep magic method private, so nobody can serialize instance.
*/
private function __sleep() {}
/**
* Make wakeup magic method private, so nobody can unserialize instance.
*/
private function __wakeup() {}
}
Użyj przykładu:
/**
* EXAMPLE
*/
/**
* @example 1 - Database class by extending SingletonClassVendor abstract class becomes fully functional singleton
* __constructor must be set to protected becaouse:
* 1 to allow instansiation from parent class
* 2 to prevent direct instanciation of object with "new" keword.
* 3 to meet requierments of SingletonClassVendor abstract class
*/
class Database extends SingletonClassVendor
{
public $type = "SomeClass";
protected function __construct(){
echo "DDDDDDDDD". PHP_EOL; // remove this line after testing
}
}
/**
* @example 2 - Config ...
*/
class Config extends SingletonClassVendor
{
public $name = "Config";
protected function __construct(){
echo "CCCCCCCCCC" . PHP_EOL; // remove this line after testing
}
}
Aby udowodnić, że działa zgodnie z oczekiwaniami:
/**
* TESTING
*/
$bd1 = Database::getInstance(); // new
$bd2 = Database::getInstance(); // old
$bd3 = Config::getInstance(); // new
$bd4 = Config::getInstance(); // old
$bd5 = Config::getInstance(); // old
$bd6 = Database::getInstance(); // old
$bd7 = Database::getInstance(); // old
$bd8 = Config::getInstance(); // old
echo PHP_EOL."COMPARE ALL DATABASE INSTANCES".PHP_EOL;
var_dump($bd1);
echo '$bd1 === $bd2' . ($bd1 === $bd2)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd2 === $bd6' . ($bd2 === $bd6)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd6 === $bd7' . ($bd6 === $bd7)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo PHP_EOL;
echo PHP_EOL."COMPARE ALL CONFIG INSTANCES". PHP_EOL;
var_dump($bd3);
echo '$bd3 === $bd4' . ($bd3 === $bd4)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd4 === $bd5' . ($bd4 === $bd5)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd5 === $bd8' . ($bd5 === $bd8)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
Cała ta złożoność („późne wiązanie statyczne” ... harumph) jest dla mnie po prostu oznaką zepsutego modelu obiektu / klasy PHP. Gdyby obiekty klasy były obiektami pierwszej klasy (patrz Python), wówczas „$ _instance” byłby zmienną instancji klasy - członkiem obiektu klasy, w przeciwieństwie do elementu / właściwości jego instancji, a także jako elementu współdzielonego przez jego potomków. W świecie Smalltalk jest to różnica między „zmienną klasy” a „zmienną instancji klasy”.
W PHP wydaje mi się, że musimy wziąć sobie do serca wskazówkę, że wzorce są przewodnikiem w pisaniu kodu - możemy być może pomyśleć o szablonie Singleton, ale próbować napisać kod, który odziedziczy z faktycznej klasy „Singleton” wygląda na mylnie dla PHP (choć przypuszczałem, że jakaś przedsiębiorcza dusza mogłaby stworzyć odpowiednie słowo kluczowe SVN).
Będę nadal kodować każdy singleton osobno, korzystając ze wspólnego szablonu.
Zauważ, że absolutnie trzymam się Z dala od dyskusji o singlach-złych, życie jest za krótkie.
Wiem, że prawdopodobnie spowoduje to niepotrzebną wojnę płomieni, ale widzę, jak możesz chcieć więcej niż jednego połączenia z bazą danych, więc zgodziłbym się z tym, że singleton może nie być najlepszym rozwiązaniem na to ... jednak istnieją inne zastosowania wzorca singletonu, które uważam za niezwykle przydatne.
Oto przykład: postanowiłem stworzyć własny silnik MVC i silnik szablonów, ponieważ chciałem czegoś naprawdę lekkiego. Jednak dane, które chcę wyświetlić, zawierają wiele specjalnych znaków matematycznych, takich jak ≥ i μ i co masz ... Dane są przechowywane jako rzeczywisty znak UTF-8 w mojej bazie danych, a nie kodowane wcześniej niż HTML, ponieważ moja aplikacja może dostarczać inne formaty, takie jak PDF i CSV oprócz HTML. Odpowiednie miejsce do formatowania HTML znajduje się w szablonie („widok”, jeśli chcesz), który jest odpowiedzialny za renderowanie tej sekcji strony (fragmentu). Chcę przekonwertować je na odpowiednie encje HTML, ale funkcja get_html_translation_table () PHP nie jest super szybka. Lepiej jest raz pobrać dane i zapisać je jako tablicę, dzięki czemu będą dostępne dla wszystkich. Tutaj' próbka, którą zapukałem, żeby przetestować prędkość. Przypuszczalnie działałoby to niezależnie od tego, czy inne metody, których używasz (po uzyskaniu instancji), są statyczne, czy nie.
class EncodeHTMLEntities {
private static $instance = null;//stores the instance of self
private $r = null;//array of chars elligalbe for replacement
private function __clone(){
}//disable cloning, no reason to clone
private function __construct()
{
$allEntities = get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES);
$specialEntities = get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES);
$this->r = array_diff($allEntities, $specialEntities);
}
public static function replace($string)
{
if(!(self::$instance instanceof self) ){
self::$instance = new self();
}
return strtr($string, self::$instance->r);
}
}
//test one million encodings of a string
$start = microtime(true);
for($x=0; $x<1000000; $x++){
$dump = EncodeHTMLEntities::replace("Reference method for diagnosis of CDAD, but clinical usefulness limited due to extended turnaround time (≥96 hrs)");
}
$end = microtime(true);
echo "Run time: ".($end-$start)." seconds using singleton\n";
//now repeat the same without using singleton
$start = microtime(true);
for($x=0; $x<1000000; $x++){
$allEntities = get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES);
$specialEntities = get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES);
$r = array_diff($allEntities, $specialEntities);
$dump = strtr("Reference method for diagnosis of CDAD, but clinical usefulness limited due to extended turnaround time (≥96 hrs)", $r);
}
$end = microtime(true);
echo "Run time: ".($end-$start)." seconds without using singleton";
Zasadniczo widziałem typowe wyniki:
test php. php Czas działania: 27,842966794968 sekund przy użyciu singletonu Czas działania: 237,78191494942 sekund bez użycia singletonu
Tak więc, chociaż z pewnością nie jestem ekspertem, nie widzę wygodniejszego i bardziej niezawodnego sposobu na ograniczenie narzutu powolnych wywołań pewnego rodzaju danych, jednocześnie czyniąc go bardzo prostym (jedna linia kodu, aby zrobić to, czego potrzebujesz). Przyznaję, że mój przykład ma tylko jedną przydatną metodę i dlatego nie jest lepszy niż funkcja zdefiniowana globalnie, ale jak tylko będziesz mieć dwie metody, będziesz chciał je zgrupować, prawda? Czy jestem daleko od bazy?
Wolę też przykłady, które faktycznie ZROBIJĄ, ponieważ czasami trudno jest wyobrazić sobie, kiedy przykład zawiera stwierdzenia takie jak „// zrób coś przydatnego tutaj”, które widzę cały czas podczas wyszukiwania samouczków.
Tak czy inaczej, chętnie przedstawię wszelkie uwagi lub komentarze na temat tego, dlaczego używanie singletonów do tego typu rzeczy jest szkodliwe (lub zbyt skomplikowane).
Ten artykuł obejmuje dość obszernie temat: http://www.phptherightway.com/pages/Design-Patterns.html#singleton
Uwaga:
- Konstruktor
__construct()
został zadeklarowany jakoprotected
uniemożliwiający utworzenie nowej instancji poza klasą za pośrednictwemnew
operatora.- Metoda magiczna
__clone()
została zadeklarowana jakoprivate
zapobiegająca klonowaniu instancji klasy za pośrednictwemclone
operatora.- Metoda magiczna
__wakeup()
została zadeklarowana jakoprivate
zapobiegająca odserializowaniu instancji klasy za pomocą funkcji globalnejunserialize()
.- Nowa instancja jest tworzona przez późne wiązanie statyczne w metodzie tworzenia statycznego
getInstance()
za pomocą słowa kluczowegostatic
. Pozwala to na podklasęclass Singleton
w przykładzie.
Napisałem dawno temu, aby podzielić się tutaj
class SingletonDesignPattern {
//just for demo there will be only one instance
private static $instanceCount =0;
//create the private instance variable
private static $myInstance=null;
//make constructor private so no one create object using new Keyword
private function __construct(){}
//no one clone the object
private function __clone(){}
//avoid serialazation
public function __wakeup(){}
//ony one way to create object
public static function getInstance(){
if(self::$myInstance==null){
self::$myInstance=new SingletonDesignPattern();
self::$instanceCount++;
}
return self::$myInstance;
}
public static function getInstanceCount(){
return self::$instanceCount;
}
}
//now lets play with singleton design pattern
$instance = SingletonDesignPattern::getInstance();
$instance = SingletonDesignPattern::getInstance();
$instance = SingletonDesignPattern::getInstance();
$instance = SingletonDesignPattern::getInstance();
echo "number of instances: ".SingletonDesignPattern::getInstanceCount();
Zgadzam się z pierwszą odpowiedzią, ale chciałbym również zadeklarować klasę jako ostateczną, aby nie można było jej rozszerzyć, ponieważ przedłużenie singletonu narusza wzorzec singletonu. Również zmienna instancji powinna być prywatna, aby nie można było uzyskać do niej bezpośredniego dostępu. Ustaw także metodę __clone jako prywatną, aby nie można było sklonować obiektu singleton.
Poniżej znajduje się przykładowy kod.
/**
* Singleton class
*
*/
final class UserFactory
{
private static $_instance = null;
/**
* Private constructor
*
*/
private function __construct() {}
/**
* Private clone method
*
*/
private function __clone() {}
/**
* Call this method to get singleton
*
* @return UserFactory
*/
public static function getInstance()
{
if (self::$_instance === null) {
self::$_instance = new UserFactory();
}
return self::$_instance;
}
}
Przykładowe użycie
$user_factory = UserFactory::getInstance();
Co powstrzymuje cię przed zrobieniem tego (co naruszałoby wzorzec singletonu ...
NIE MOŻESZ TEGO ZROBIĆ!
$user_factory = UserFactory::$_instance;
class SecondUserFactory extends UserFactory { }
To powinna być właściwa droga Singletona.
class Singleton {
private static $instance;
private $count = 0;
protected function __construct(){
}
public static function singleton(){
if (!isset(self::$instance)) {
self::$instance = new Singleton;
}
return self::$instance;
}
public function increment()
{
return $this->count++;
}
protected function __clone(){
}
protected function __wakeup(){
}
}
Podobał mi się sposób użycia cech @ jose-segura, ale nie podobała mi się potrzeba definiowania zmiennej statycznej dla podklas. Poniżej znajduje się rozwiązanie, które pozwala tego uniknąć poprzez buforowanie instancji w statycznej zmiennej lokalnej do metody fabrycznej indeksowanej według nazwy klasy:
<?php
trait Singleton {
# Single point of entry for creating a new instance. For a given
# class always returns the same instance.
public static function instance(){
static $instances = array();
$class = get_called_class();
if( !isset($instances[$class]) ) $instances[$class] = new $class();
return $instances[$class];
}
# Kill traditional methods of creating new instances
protected function __clone() {}
protected function __construct() {}
}
Użycie jest takie samo jak @ jose-segura, tylko brak potrzeby zmiennej statycznej w podklasach.
Klasa bazy danych, która sprawdza, czy istnieje instancja bazy danych, zwróci poprzednią instancję.
class Database {
public static $instance;
public static function getInstance(){
if(!isset(Database::$instance) ) {
Database::$instance = new Database();
}
return Database::$instance;
}
private function __cunstruct() {
/* private and cant create multiple objects */
}
public function getQuery(){
return "Test Query Data";
}
}
$dbObj = Database::getInstance();
$dbObj2 = Database::getInstance();
var_dump($dbObj);
var_dump($dbObj2);
/*
After execution you will get following output:
object(Database)[1]
object(Database)[1]
*/
Zobacz http://www.phptechi.com/php-singleton-design-patterns-example.html
To jest przykład tworzenia singletona w klasie Database
wzory projektowe 1) singleton
class Database{
public static $instance;
public static function getInstance(){
if(!isset(Database::$instance)){
Database::$instance=new Database();
return Database::$instance;
}
}
$db=Database::getInstance();
$db2=Database::getInstance();
$db3=Database::getInstance();
var_dump($db);
var_dump($db2);
var_dump($db3);
to out put to -
object(Database)[1]
object(Database)[1]
object(Database)[1]
użyj tylko jednej instancji, nie twórz 3 instancji
Szybki przykład:
final class Singleton
{
private static $instance = null;
private function __construct(){}
private function __clone(){}
private function __wakeup(){}
public static function get_instance()
{
if ( static::$instance === null ) {
static::$instance = new static();
}
return static::$instance;
}
}
Mam nadzieję, że pomoc.
Oto mój przykład, który zapewnia możliwość wywoływania jako $ var = new Singleton (), a także tworzenie 3 zmiennych w celu przetestowania, czy tworzy nowy obiekt:
class Singleton{
private static $data;
function __construct(){
if ($this::$data == null){
$this->makeSingleton();
}
echo "<br/>".$this::$data;
}
private function makeSingleton(){
$this::$data = rand(0, 100);
}
public function change($new_val){
$this::$data = $new_val;
}
public function printme(){
echo "<br/>".$this::$data;
}
}
$a = new Singleton();
$b = new Singleton();
$c = new Singleton();
$a->change(-2);
$a->printme();
$b->printme();
$d = new Singleton();
$d->printme();