Почему черты не могут быть созданы непосредственно?

При тестировании признаков в PHP я был немного озадачен, почему были введены признаки. Я провел небольшой эксперимент. Сначала я вызвал методы черты прямо в классе

<?php

trait HelloWorld {
public function sayHello() {
echo 'Hello World!';
}
}

class TheWorldIsNotEnough {
use HelloWorld;
public function sayHellos() {
$o = new HelloWorld();
$o->sayHello();
}
}

$o = new TheWorldIsNotEnough();
$o->sayHellos();

?>

Я получил ошибку

Fatal error: Cannot instantiate trait HelloWorld in C:\xampp\htdocs\test.php on line 35

Но когда я это сделал

<?php

trait HelloWorld {
public function sayHello() {
echo 'Hello World!';
}
}
class MyHelloWorld {
use HelloWorld;
}
class TheWorldIsNotEnough {
use HelloWorld;
public function sayHellos() {
$o = new MyHelloWorld();
$o->sayHello();
}
}

$o = new TheWorldIsNotEnough();
$o->sayHellos();

?>

я смог вызвать метод черты, и результат отобразил «Hello World!».
Так в чем же преимущество использования Черт и чем оно отличается от абстрактных классов? Пожалуйста, помогите мне понять использование. Благодарю.

1

Решение

Traits не должны быть созданы. Это просто части кода, которые вы можете использовать в своих классах useих Вы можете себе представить, что trait код расширяется и становится частью вашего класса. Даже грустно, что:

Черты, по сути, с помощью языка копировать и вставлять.

Итак, ваш пример должен работать так:

<?php

trait HelloWorld {
public function sayHello() {
echo 'Hello World!';
}
}

class TheWorldIsNotEnough {
use HelloWorld;

public function sayHellos() {
// your trait defines this method, so now you can
// think that this method is defined in your class directly
$this->sayHello();
}
}

$o = new TheWorldIsNotEnough();
$o->sayHellos();

//or simply
$o->sayHello();
?>
7

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

Хорошо, так что, возможно, это НЕ СПОСОБ сделать это, но я решил, как использовать черты и почему это лучше в некоторых случаях для моих проектов. Они являются своего рода расширением для классов. Если вы знакомы с CakePHP, эти черты напоминают мне о поведении моделей или компонентов для контроллеров. Просто посмотрите 🙂

Ну, абстрактный класс немного отличается, потому что вы можете использовать его для наследования так:

abstract class HelloWorld {
public function sayHello() {
echo "Hello World!";
}

abstract public function doFunnyStuff();
abstract public function doMoreFunnyStuff();
}

class ConcreteHelloWorld extends HelloWorld {
public function doFunnyStuff() {
echo "Funny Hello!";
}

public function doMoreFunnyStuff() {
echo "More Funny Hello!";
}
}

$o = new ConcreteHelloWorld();
$o->sayHello(); // common property
$o->doFunnyStuff(); // specialy implemented property
$o->doMoreFunnyStuff(); // specialy impelemented property

Черта больше похожа на расширение класса. Я использую черты в MVC Framework для расширения классов с ведением журнала следующим образом:

trait Logger
{
public function saveLog($kindOf, $messasge, $serverity)
{
some_connect_to_DB_pseudo_code();
$sqlQuery = "INSERT INTO log (kindof, message, serverity)
VALUES (".$kindof.", ".$message.", ".$serverity.")";
mysql_query($sqlQuery); // deprecated :-)
}
}

class Controller extends AppController
{
use Logger;

public function someAction($params)
{
$this->saveLog("CALL", __METHOD__." - started some Action with params: ".$params, 0);

...
...
}
}

Это очень удобно, так как я использую его в каждом классе, и мне не нужно снова писать все эти строки, где мне нужно подключиться к базе данных и сгенерировать SQL-запрос. И так как у меня много наследования через всю инфраструктуру MVC, мне не нужно включать Logger как некоторый родительский класс. Просто поместите его с ключевым словом «use» в любой класс, который сможет отправлять loginfo в базу данных.

То же самое работает для меня с отладочными сообщениями, где я просто пишу что-то вроде этого:

$this->debug("WARNING", $message);

И моя черта отладки создает красиво отформатированное предупреждающее сообщение 🙂 Надеюсь, это поможет понять.

1

Спасибо всем, кто опубликовал ответ, но ответ, который я действительно искал, я получил после многих исследований. Мой вопрос заключался в том, что отличает Traits от существующих методов, таких как абстрактный класс, наследование и т. Д. Суть в том, что он создается при вызове внутри класса, это нормально, но самое большое отличие состоит в том, что мы можем включить несколько признаков в класс таким образом.

use class1, class2;

В случае конфликта, когда в обоих классах существуют одни и те же методы, и мы хотим использовать методы из класса 2, мы делаем это

use class1, class2 {
class2::method1 insteadof class1;
}

Даже черты могут иметь несколько черт, определенных следующим образом:

trait Class1 {
use trait1, trait2;
}

В отличие от наследования; если признак имеет статические свойства, каждый класс, использующий эту особенность, имеет независимые экземпляры этих свойств.
Проверьте эту ссылку http://php.net/manual/en/language.oop5.traits.php#107965

Другое отличие черт от наследования состоит в том, что методы, определенные в чертах, могут получить доступ к методам и свойствам класса, в котором они используются, включая частные. http://php.net/manual/en/language.oop5.traits.php#109508.

Кроме того, в отличие от реализации интерфейса, все методы признаков могут быть доступны без их повторного определения.

1

Единственная общая вещь между Abstract и Trait класс является то, что невозможно создать экземпляр a Trait/an Abstract сам по себе.

Но их цель другая. Trait предназначен только для группирования функциональных возможностей детальным и последовательным образом. Это должно уменьшить некоторые ограничения одиночного наследования, позволяя разработчику reuse sets of methods freely в нескольких независимых классах, живущих в разных иерархиях классов, где Abstract классы предназначены только для того, чтобы предоставить своего рода шаблон для наследования и заставить наследующий класс реализовать абстрактные методы.

0
По вопросам рекламы [email protected]