Например:
$m = new mysqli('host', 'user', 'pass', 'db');
$q = $m->query('SELECT stuff FROM table');
while ($row = $q->fetch_assoc()) {
// do stuff
}
Как работает query
метод в конечном итоге имеет свои собственные «под-методы», такие как fetch_assoc()
?
Как я могу повторить это поведение с помощью ООП?
РЕДАКТИРОВАТЬ … будет ли это считаться правильным и / или хорошей практикой?
class MyClass {
function myMethod() {
return new AnotherClass();
}
}
class AnotherClass {
function __construct() {
$this->stuff = 'stuff';
}
}
Тогда я могу сделать:
$obj = new MyClass;
$stuff_getter = $obj->myMethod();
echo $stuff_getter->stuff;
Это немного мнение, основанное на том, что вы спрашиваете, но, поскольку я думаю, что многие люди борются с этим, я предоставлю некоторую общую информацию об этом случае.
Прежде всего, вы не можете сказать, является ли это хорошей практикой или нет. Это зависит от намерения и контекста. Смотрите этот код:
class MyClass {
function myMethod() {
return new AnotherClass();
}
}
Это нормально? Да, это нормально, что вы делаете, но обратите внимание, что у вас есть сильная зависимость здесь. Если вы хотите по какой-то причине иметь разные реализации
из AnotherClass
вам нужно изменить код.
Вы можете предотвратить это с помощью внедрения зависимостей. Реализовать интерфейс в AnotherClass
и ввести его в MyClass
,
Когда у вас есть другая реализация AnotherClass
Вы можете просто передать его как «старую» версию.
Как это реализовать, также зависит от цели вашего кода, но я приведу базовый пример вашего кода.
class MyClass {
private $aClass = null;
function __construct($aClass)
{
$this->aClass = $aClass;
}
function myMethod() {
return new $this->aClass();
}
}
interface AnInterface
{
}
class AnotherClass implements AnInterface {
function __construct() {
$this->stuff = 'stuff';
}
}$obj = new MyClass(new AnotherClass());
$stuff_getter = $obj->myMethod();
echo $stuff_getter->stuff;
Теперь, используя это, я могу просто создать другую реализацию AnotherClass
и передать его MyClass
как я всегда делал. Вместо вашего сценария, где мне нужно добавить еще одну функцию. Например:
class AnotherClass2 implements AnInterface {
function __construct() {
$this->stuff = 'another stuff';
}
}
$obj = new MyClass(new AnotherClass2());
$stuff_getter = $obj->myMethod();
echo $stuff_getter->stuff;
Во-вторых, я замечаю, что вы не определяете переменные. Я думаю, что это немного основано на мнении, но я категорически против публичных переменных (что в вашем случае по умолчанию).
Создайте переменную и назначьте ее в своем конструкторе. Создавайте геттеры и сеттеры (если вы ленивы, вы можете создавать магические геттеры и сеттеры (посмотреть здесь). Вы бы получили что-то вроде этого:
class AnotherClass implements AnInterface {
private $stuff;
function __construct() {
$this->stuff = 'stuff';
}
public function getStuff()
{
return $this->stuff;
}
}
$obj = new MyClass(new AnotherClass());
$stuff_getter = $obj->myMethod();
echo $stuff_getter->getStuff();
Я надеюсь, что это проясняет вашу конструкцию, хотя это может не полностью ответить на ваш вопрос.
Две заметки по этому поводу.
Ваш окончательный код может быть (как пример интерфейса) что-то вроде этого:
class MyClass {
private $aClass = null;
function __construct($aClass)
{
$this->aClass = $aClass;
}
function myMethod() {
return new $this->aClass();
}
}
interface AnInterface
{
public function getStuff();
}
class AnotherClass implements AnInterface {
private $stuff;
function __construct() {
$this->stuff = 'stuff';
}
public function getStuff()
{
return $this->stuff;
}
}
class AnotherClass2 implements AnInterface {
private $stuff;
function __construct() {
$this->stuff = 'another stuff';
}
public function getStuff()
{
return $this->stuff;
}
}$obj = new MyClass(new AnotherClass());
$stuff_getter = $obj->myMethod();
echo $stuff_getter->getStuff();
$obj = new MyClass(new AnotherClass2());
$stuff_getter = $obj->myMethod();
echo $stuff_getter->getStuff();
Других решений пока нет …