0

Gives an error:

Target [MyVendor\ProductList\ProductServiceInterface] is not instantiable.

ProductServiceInterface

namespace MyVendor\ProductList;

interface ProductServiceInterface
{
    public function productList();
    public function getProductSpeed();
}

ProductColorService

namespace MyVendor\ProductList\Service;

abstract class ProductColorService implements \MyVendor\ProductList\ProductServiceInterface
{
    public function productList()
    {
        $color = "black";
        return $color;
    }
}

** ProductSpeedService **

namespace MyVendor\ProductList\Service;

abstract class ProductSpeedService implements \MyVendor\ProductList\ProductServiceInterface {

    public function getProductSpeed() {
        $speed = 200;
        return $speed;
    }


}

Provider :

namespace MyVendor\ProductList;

use Illuminate\Support\ServiceProvider;
use MyVendor\ProductList\ProductServiceInterface;
use MyVendor\ProductList\Service\ProductColorService;

class ProductColorServiceProvider extends ServiceProvider
{
    public function boot()
    {
        $this->loadRoutesFrom(__DIR__ . '/routes/color.php');
    }

    public function register()
    {
        $this->app->bind('MyVendor\ProductList\ProductServiceInterface','MyVendor\ProductList\Service\ProductColorService');

        $this->app->bind('MyVendor\ProductList\ProductServiceInterface','MyVendor\ProductList\Service\ProductSpeedService');
    }
}

Whats wrong in this code? Actually I need to override some functions in interface using service. ie each service should override one method.

namespace MyVendor\ProductList\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use MyVendor\ProductList\Models\Product;
use MyVendor\ProductList\ProductServiceInterface;

class ProductListController extends Controller
{
    public function index(ProductServiceInterface $product_service)
    {
        $color = $product_service->productList();
        $speed = $product_service->getProductSpeed();
        dd($color," = ",$speed);
        $product = Product::get();
        return view('ProductList::product',compact('product'));
    }
}

here productList() in one service and productSpeed() from another service

James Z
  • 12,209
  • 10
  • 24
  • 44
Nidhin
  • 1
  • 4
  • you didn't implement `getProductSpeed` btw ,.. and you only have one binding for that interface, you need to explain more what you are trying to do because ProductServiceInterface in this context can only resolve to one concrete that implements ProductServiceInterface and ProductColorService is abstract so it can't be concrete (can't be a binding for the interface because it can't be instantiated) – lagbox Nov 24 '19 at 08:05
  • Thanks for your reply, sorry to include productSpeedService i have just edit the question, i need to add some conditions from each service and get all these conditions from the controller via the interface – Nidhin Nov 24 '19 at 08:21
  • this isn't how things work ... `$product_service` is a single object of a class that implements the interface ... multiple bindings to a single interface will override one another, you can only do this with Contextual Bindings, which would not help here and even then you are not getting pieces of different classes, besides the fact that ProductColorService is **abstract** – lagbox Nov 24 '19 at 08:26
  • i coudn't get you, i just need to override one function from one service , so from each service i will override only one function and from controller ,i want all the values – Nidhin Nov 24 '19 at 08:29
  • with out using abstract it gives error – Nidhin Nov 24 '19 at 08:30
  • the bindings do not do what you want ... you would need to create a class that does what you want for these 2 methods – lagbox Nov 24 '19 at 08:30
  • can you show me the codes ? ,the class for 2 methods – Nidhin Nov 24 '19 at 08:32
  • you need to clarify why you think you need this setup, because it wont work. why does there need to be one service that provides both of these things from these 2 abstracts .... do the abstract classes even need to exist, why can't this be combined into one class – lagbox Nov 24 '19 at 08:39
  • i got a question to write package for product list with one end point , and it shoud have multiple service , each one has some conditions on listing the ** -Package which returns the available products with the conditions added in each service. - Each service can be a class which is implemented from an interface and registered ** so i made a try on this method – Nidhin Nov 24 '19 at 08:45
  • this sounds like an X Y problem ... i think you are going to need to update your question with what you actually need to achieve and point out that this is what you tried, not that this is the end result (because you can't do this the way you are trying) and might get some good answers :) – lagbox Nov 24 '19 at 08:50

1 Answers1

1

You can't instantiate abstract classes. The whole point of them is there can never be an instance of them, so if you bind your interface to your abstract class with a method, it simply can never be abstract. Abstract is for classes in inheritance structures you do not want to have the users to create new ones.

So there is no reason for the abstract, abstract is for something like this.

abstract class Vehicle {
    protected $wheels;

    public function getWheels() {
        return $this->wheels;
    }
}

class Car extends Vehicle {
    protected $wheels = 4;
}

class Bike extends Vehicle {
    protected $wheels = 2;
}

You can not make a vehicle as it is not a concrete implementation, as it is a parent class to help with methods shared across two classes. So short version, just remove the abstract keyword. If you don't know why you add it, it is not needed.

mrhn
  • 17,961
  • 4
  • 27
  • 46
  • i have more than one methods in an interface , and override each method from seperate services , ie one service for one method() in interface , so then how can i implement it? – Nidhin Nov 24 '19 at 17:13
  • Why does the class have to be abstract? abstract means you cant instantiate it – mrhn Nov 24 '19 at 17:31