Interface or Abstract Class

Interface or Abstract Class

I was recently working on a project, and I found myself adding the @property DocBlock to an interface. I knew it wasn’t good practice, but the class that is implementing that interface will provide those properties. I tried to convince myself it was okay.

Interface

Yes, it is a good idea to have your concrete classes implement an interface. It helps you plan how the class should work. Another benefit is using the interface as a type hint, you can then pass your concrete class as the parameter. This also allows someone to create their own implementation of the interface and pass it as a parameter.

An interface is essentially a signature. It can’t really do anything except provide a skeleton of what the class has to implement. You can’t declare properties, you can’t write any logic, and it can’t cook you breakfast. Although it can’t do much, you’ll usually use an interface instead of an abstract class.

Since an interface can’t define properties, what I was doing, was wrong. There was no agreement between the interface and the concrete class that said it must implement those properties. It is undefined behavior and would cause headaches down the road.

Example


<?php

interface CreateDropletRequestContract {
	public function __construct($name, $region, $size, $image);
}

class CreateDropletRequest implements CreateDropletRequestContract {
	// . . .
	private $name;
	private $region;
	private $size;
	private $image;

	public function __construct($name, $region, $size, $image) {
		$this->name = $name;
		$this->region = $region;
		$this->size = $size;
		$this->image = $image;
	}
	// . . .
}

Abstract Class

An abstract class can not be instantiated. With an abstract class, you don’t implement it, you extend it. Since the abstract class can provide logic, you must extend it to keep the logic. When you implement something, that means you are going to write the logic for it. Abstract classes can also define properties, which was I needed to do for my project.

A concrete class can only extend one class, but it can implement many interfaces. So when you are thinking everything out, try to plan ahead, even if it’s hard or you end up being wrong. The more you plan, the better you’ll get at doing it, and the easier it will become.

Example


<?php

abstract class CreateDropletRequestContract {
	private $name;
	private $region;
	private $size;
	private $image;

	public function __construct($name, $region, $size, $image) {
		$this->name = $name;
		$this->region = $region;
		$this->size = $size;
		$this->image = $image;
	}
}

class CreateDropletRequest extends CreateDropletRequestContract {
	// . . .
	// Most of the code could already be written in the abstract class.
	// . . .
}

Conclusion

I might ditch the abstract class and only implement the concrete class since it is only a data transfer object without an interface. Feel free to send me an email if you have any questions.

Example


<?php

class CreateDropletRequest extends RequestContract {
	// . . .
	private $name;
	private $region;
	private $size;
	private $image;

	public function __construct($name, $region, $size, $image) {
		$this->name = $name;
		$this->region = $region;
		$this->size = $size;
		$this->image = $image;
	}
	// . . .
}