Добавить анонимную функцию в массив в классе

Я новичок в 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');

?>

1

Решение

Вы не можете назначать произвольные выражения в объявлении свойства, например, только постоянные значения или с недавними изменениями в синтаксическом анализаторе определенные выражения с постоянными значениями.

Однако объявление свойств с начальным значением на самом деле является просто сокращением для объявления свойства и последующей его инициализации в конструкторе, поскольку первоначальное присваивание происходит всякий раз, когда создается новый экземпляр.

Таким образом, два класса ниже будут вести себя одинаково:

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]
];
}
}
1

Другие решения

Вы можете только инициализировать поле со значением константы во время компиляции. Я предполагаю, что анонимная функция не считается постоянной величиной.

0