Во-первых, это не что-то особенное, что касается Laravel, это просто считается лучшей практикой в целом.
Если вы введете конкретный класс, вы только что создали жесткую зависимость.
Если вы вводите интерфейс, вы можете использовать тот же код, но просто вводите разные классы (например: настоящий класс DB для prod и класс Mock DB для тестов), который реализует этот же интерфейс.
На самом деле, вы всегда вводить конкретные классы, это просто тип намекая, что это интерфейс вместо конкретного класса
Пример:
class DB implements DBInterface
{
// A bunch of methods fetching from real DB
}
class MockDB implements DBInterface
{
// Has the same (interface) methods but returns some fixed data for testing.
}
class Posts
{
public function __construct(DBInterface $db)
{
$this->db = $db;
}
public function get()
{
$this->db->query("....");
}
}
$posts = new Posts(new DB);
$data = $posts->get(); // This fetches from the real db
// And for testing
$posts = new Posts(new MockDB);
$data = posts->get(); // Fetches from the mock DB instead
Сила этого является то, что класс, который вы» re-инъекция будет иметь одну и ту же подпись класса, но может иметь совершенно разные реализации. Вашему классу Posts
не нужно заботиться о том, какую реализацию он получает ...
Это просто быстрый пример, но он объясняет одно, и действительно хорошее, использование интерфейсов в качестве типов подсказок ...
Perfect Magnus. Это действительно хороший ответ. Конечно, я знаю, что я впрыскиваю конкретный класс и набираю тип интерфейса, но ... Я не знал, почему тип подсказывает интерфейс, а не конкретный класс напрямую. Спасибо! –