匿名类

PHP 7 开始支持匿名类。 匿名类很有用,可以创建一次性的简单对象。

<?php

// PHP 7 之前的代码
class Logger
{
    public function 
log($msg)
    {
        echo 
$msg;
    }
}

$util->setLogger(new Logger());

// 使用了 PHP 7+ 后的代码
$util->setLogger(new class {
    public function 
log($msg)
    {
        echo 
$msg;
    }
});

可以传递参数到匿名类的构造器,也可以扩展(extend)其他类、实现接口(implement interface),以及像其他普通的类一样使用 trait:

<?php

class SomeClass {}
interface 
SomeInterface {}
trait 
SomeTrait {}

var_dump(new class(10) extends SomeClass implements SomeInterface {
    private 
$num;

    public function 
__construct($num)
    {
        
$this->num $num;
    }

    use 
SomeTrait;
});

以上例程会输出:

object(class@anonymous)#1 (1) { ["Command line code0x104c5b612":"class@anonymous":private]=> int(10)
}

匿名类被嵌套进普通 Class 后,不能访问这个外部类(Outer class)的 private(私有)、protected(受保护)方法或者属性。 为了访问外部类(Outer class)protected 属性或方法,匿名类可以 extend(扩展)此外部类。 为了使用外部类(Outer class)的 private 属性,必须通过构造器传进来:

<?php

class Outer
{
    private 
$prop 1;
    protected 
$prop2 2;

    protected function 
func1()
    {
        return 
3;
    }

    public function 
func2()
    {
        return new class(
$this->prop) extends Outer {
            private 
$prop3;

            public function 
__construct($prop)
            {
                
$this->prop3 $prop;
            }

            public function 
func3()
            {
                return 
$this->prop2 $this->prop3 $this->func1();
            }
        };
    }
}

echo (new 
Outer)->func2()->func3();

以上例程会输出:

6
add a note

User Contributed Notes 3 notes

up
3
Anonymous
1 month ago
Below three examples describe anonymous class with very simple and basic but quite understandable example

<?php
// First way - anonymous class assigned directly to variable
$ano_class_obj = new class{
    public
$prop1 = 'hello';
    public
$prop2 = 754;
    const
SETT = 'some config';

    public function
getValue()
    {
       
// do some operation
       
return 'some returned value';
    }

    public function
getValueWithArgu($str)
    {
       
// do some operation
       
return 'returned value is '.$str;
    }
};

echo
"\n";

var_dump($ano_class_obj);
echo
"\n";

echo
$ano_class_obj->prop1;
echo
"\n";

echo
$ano_class_obj->prop2;
echo
"\n";

echo
$ano_class_obj::SETT;
echo
"\n";

echo
$ano_class_obj->getValue();
echo
"\n";

echo
$ano_class_obj->getValueWithArgu('OOP');
echo
"\n";

echo
"\n";

// Second way - anonymous class assigned to variable via defined function
$ano_class_obj_with_func = ano_func();

function
ano_func()
{
    return new class {
        public
$prop1 = 'hello';
        public
$prop2 = 754;
        const
SETT = 'some config';

        public function
getValue()
        {
           
// do some operation
           
return 'some returned value';
        }

        public function
getValueWithArgu($str)
        {
           
// do some operation
           
return 'returned value is '.$str;
        }
    };
}

echo
"\n";

var_dump($ano_class_obj_with_func);
echo
"\n";

echo
$ano_class_obj_with_func->prop1;
echo
"\n";

echo
$ano_class_obj_with_func->prop2;
echo
"\n";

echo
$ano_class_obj_with_func::SETT;
echo
"\n";

echo
$ano_class_obj_with_func->getValue();
echo
"\n";

echo
$ano_class_obj_with_func->getValueWithArgu('OOP');
echo
"\n";

echo
"\n";

// Third way - passing argument to anonymous class via constructors
$arg = 1; // we got it by some operation
$config = [2, false]; // we got it by some operation
$ano_class_obj_with_arg = ano_func_with_arg($arg, $config);

function
ano_func_with_arg($arg, $config)
{
    return new class(
$arg, $config) {
        public
$prop1 = 'hello';
        public
$prop2 = 754;
        public
$prop3, $config;
        const
SETT = 'some config';

        public function
__construct($arg, $config)
        {
           
$this->prop3 = $arg;
           
$this->config =$config;
        }

        public function
getValue()
        {
           
// do some operation
           
return 'some returned value';
        }

        public function
getValueWithArgu($str)
        {
           
// do some operation
           
return 'returned value is '.$str;
        }
    };
}

echo
"\n";

var_dump($ano_class_obj_with_arg);
echo
"\n";

echo
$ano_class_obj_with_arg->prop1;
echo
"\n";

echo
$ano_class_obj_with_arg->prop2;
echo
"\n";

echo
$ano_class_obj_with_arg::SETT;
echo
"\n";

echo
$ano_class_obj_with_arg->getValue();
echo
"\n";

echo
$ano_class_obj_with_arg->getValueWithArgu('OOP');
echo
"\n";

echo
"\n";
up
1
Theriault
1 month ago
Despite being anonymous, anonymous classes are named. get_declared_classes() will return anonymous classes (PHP 7.0.5).

Because they are named, an anonymous class can also be aliased (not that its useful):
<?php
$a
= new class { public $test = 123; };
class_alias(get_class($a), "Test");
$b = new Test;
echo
$b->test; // outputs 123
?>

Unlike anonymous functions, returning an anonymous class from a function will be a new instance of the SAME anonymous class each time.

<?php
function anonymous_function () {
   return function () {
      static
$shared = 0;
      echo ++
$shared;
   };
};
function
anonymous_class() {
   return new class {
      static
$shared = 0;
      public function
__construct() {
         echo ++
self::$shared;
      }
   };
}

anonymous_function(); // outputs 1
anonymous_function(); // outputs 1

anonymous_class(); // outputs 1
anonymous_class(); // outputs 2

get_class(anonymous_class()) === get_class(anonymous_class()); // TRUE
?>
up
-2
sam dot wankaner at gmail dot com
1 month ago
Below two examples describe anonymous class with very simple and basic but quite understandable example

<?php
// anonymous_class.php
// PHP 7

// First way - anonymous class assigned directly to variable
$ano_class_obj = new class{
    public
$prop1 = 'hello';
    public
$prop2 = 754;
    const
SETT = 'some config';

    public function
getValue()
    {
       
// do some operation
       
return 'some returned value';
    }

    public function
getValueWithArgu($str)
    {
       
// do some operation
       
return 'returned value is '.$str;
    }
};

echo
"\n";

var_dump($ano_class_obj);
echo
"\n";

echo
$ano_class_obj->prop1;
echo
"\n";

echo
$ano_class_obj->prop2;
echo
"\n";

echo
$ano_class_obj::SETT;
echo
"\n";

echo
$ano_class_obj->getValue();
echo
"\n";

echo
$ano_class_obj->getValueWithArgu('OOP');
echo
"\n";

echo
"\n";

// Second way - anonymous class assigned to variable via defined function
$ano_class_obj_with_func = ano_func();

function
ano_func()
{
    return new class {
        public
$prop1 = 'hello';
        public
$prop2 = 754;
        const
SETT = 'some config';

        public function
getValue()
        {
           
// do some operation
           
return 'some returned value';
        }

        public function
getValueWithArgu($str)
        {
           
// do some operation
           
return 'returned value is '.$str;
        }
    };
}

echo
"\n";

var_dump($ano_class_obj_with_func);
echo
"\n";

echo
$ano_class_obj_with_func->prop1;
echo
"\n";

echo
$ano_class_obj_with_func->prop2;
echo
"\n";

echo
$ano_class_obj_with_func::SETT;
echo
"\n";

echo
$ano_class_obj_with_func->getValue();
echo
"\n";

echo
$ano_class_obj_with_func->getValueWithArgu('OOP');
echo
"\n";

echo
"\n";

// Third way - passing argument to anonymous class via constructors
$arg = 1; // we got it by some operation
$config = [2, false]; // we got it by some operation
$ano_class_obj_with_arg = ano_func_with_arg($arg, $config);

function
ano_func_with_arg($arg, $config)
{
    return new class(
$arg, $config) {
        public
$prop1 = 'hello';
        public
$prop2 = 754;
        public
$prop3, $config;
        const
SETT = 'some config';

        public function
__construct($arg, $config)
        {
           
$this->prop3 = $arg;
           
$this->config =$config;
        }

        public function
getValue()
        {
           
// do some operation
           
return 'some returned value';
        }

        public function
getValueWithArgu($str)
        {
           
// do some operation
           
return 'returned value is '.$str;
        }
    };
}

echo
"\n";

var_dump($ano_class_obj_with_arg);
echo
"\n";

echo
$ano_class_obj_with_arg->prop1;
echo
"\n";

echo
$ano_class_obj_with_arg->prop2;
echo
"\n";

echo
$ano_class_obj_with_arg::SETT;
echo
"\n";

echo
$ano_class_obj_with_arg->getValue();
echo
"\n";

echo
$ano_class_obj_with_arg->getValueWithArgu('OOP');
echo
"\n";

echo
"\n";