Я новичок в PHP, но немного работал с JavaScript. Я пытался сделать следующее:
class MyClass {
private $someAnonymousFunction = function($any){
return $any;
};
$data = [
['some String', $someAnonymousFunction]
];
}
Но возникает ошибка, когда я создаю someAnonymousFunction
говоря это не нравится, что я положил function
(unexpected 'function' (T_FUNCTION)
) там так. Я пробовал разные сценарии помимо приведенного выше примера, но, похоже, происходят те же ошибки.
Обновить Почему я хочу это сделать. Я хочу сделать это, потому что я хочу абстрагироваться от большей части основной темы при создании классов. Если я собираюсь писать код снова и снова, я бы хотел сделать его максимально простым и понятным. Ниже приведен мой код полностью (обратите внимание, что это было только для класса, и я взял его далеко за рамки того, что должно быть):
abstract class Protection {
const Guard = 0;
const Open = 1;
}
abstract class __ {
public function identity($any) {
return $any;
}
}
// This is the core logic behind the class
trait Property {
public function get($name) {
if ($this->data[$name][1] == Protection::Open) {
return $this->data[$name][0];
}
else {
//throw error
}
}
public function set($name, $set) {
if ($this->data[$name][1] == Protection::Open) {
//Guard function can throw error or filter input
$func = $this->data[$name][2];
$this->data[$name][0] = $func($set);
return $this;
}
else {
// throw error
}
}
}
class Monster {
use Property;
//Just trying to get this to work. Throws error.
private $identity = function($any) {
return $any;
};
private $data = [
'hairColor' => [
'brown',
Protection::Open,
ucwords
],
'killType' => [
'sword',
Protection::Open,
__::identity //Doesn't work either thinks it's a constant.
]
];
}$generic = new Monster();
echo '<br> Hair color: ' . $generic->get('hairColor') . ', Kill type: '
. $generic->get('killType') . '<br>';
$generic->set('hairColor', 'blue')->set('killType', 'silver bullet');
Обновление 2: Вот «окончательный» код:
<?php
class Utils {
static function identity($any) {
return $any;
}
}
// Property abstracts much of the boiler plate away
// from making classes with getters and setters.
// It is chainable by default.
// It takes a variable named `data` which holds an
// associative array, with the keys being the names
// of the properties/methods. The key holds a value
// which is an indexed array where:
// Index 0 == Value of property.
// [Index 1] == Optional string name of guard function.
// [Index 2] == Optional string name of method called
// with `get` method.
// It has two public methods:
// `get` returns value of property or calls a method.
// `set` gives a new value to a property.
trait Property {
// Create a new property with attributes in an array.
private function createNewProperty($name, $set) {
$this->data[$name] = (is_array($set)) ? $set : [$set];
}
// Return property value
public function get($name) {
// If the property doesn't exist throw an error.
if (!isset($this->data[$name])) {
throw new Exception('No such property or method '.$name);
}
// copy by reference value into differently
// named variable to make code more concise.
$prop =& $this->data[$name];
// determine if property is a method.
if (isset($prop[2]) && $prop[2]) {
// call method with property value
return call_user_func($prop[2], $prop[0]);
}
else {
//return plain property value
return $prop[0];
}
}
// Set property value
public function set($name, $set) {
// If property isn't set then create one
if (!isset($this->data[$name])) {
createNewProperty($name, $set);
}
// copy by reference value into differently
// named variable to make code more concise.
$prop =& $this->data[$name];
// determine if guards exist when setting property
if (isset($prop[1]) && $prop[1]) {
$prop[0] = call_user_func($prop[1], $set);
return $this; // make chainable
}
else {
// set plain property
$prop[0] = $set;
return $this; // make chainable
}
}
}
class Monster {
use Property;
private $data = [
'hairColor' => ['brown', ['Utils', 'identity']],
'killType' => ['sword', 'ucwords'],
'simple' => ['simple value', null, 'ucwords'],
];
}
$generic = new Monster();
echo '<br> Hair color: ' . $generic->get('hairColor') . ', Kill type: '
. $generic->get('killType') . '<br>';
$generic->set('hairColor', 'blue')->set('killType', 'silver bullet');
echo '<br> Hair color: ' . $generic->get('hairColor') . ', Kill type: '
. $generic->get('killType') . '<br>';
echo '<br>Simple: '.$generic->get('simple');
$generic->set('simple', 'simple value changed!');
echo '<br>Simple: '.$generic->get('simple');
?>
Вы не можете назначать произвольные выражения в объявлении свойства, например, только постоянные значения или с недавними изменениями в синтаксическом анализаторе определенные выражения с постоянными значениями.
Однако объявление свойств с начальным значением на самом деле является просто сокращением для объявления свойства и последующей его инициализации в конструкторе, поскольку первоначальное присваивание происходит всякий раз, когда создается новый экземпляр.
Таким образом, два класса ниже будут вести себя одинаково:
class Foo1 {
private $bar = 42;
}
class Foo2 {
private $bar;
public function __construct() {
$this->bar = 42;
}
}
Поскольку нет никаких ограничений на присваивания, которые вы можете сделать в конструкторе, это позволяет вам переписать ваш код как этот (вы пропустили спецификатор доступа на $data
так что я предположил private
):
class MyClass {
private $someAnonymousFunction;
private $data;
public function __construct() {
$this->someAnonymousFunction = function($any){
return $any;
};
$this->data = [
['some String', $this->someAnonymousFunction]
];
}
}
Вы можете только инициализировать поле со значением константы во время компиляции. Я предполагаю, что анонимная функция не считается постоянной величиной.