When defining the structure and inheriting Interface and/or Abstract Class, which one is the best practice? And why? Here are 2 examples:
Here is the example for [Interface] -> [Abstract Class] -> [Class]
Interface DataInterface
{
public function __construct($connection);
public function connected();
public function get();
}
Abstract class BaseData implements DataInterface
{
protected $connection;
public function __construct($connection)
{
$this->connection = $connection;
}
}
class UserData extends BaseData
{
public function exists()
{
return is_connected($this->connection);
}
public function get()
{
return get_data($this->connection);
}
}
$oUserData = new UserData(new Connection());
And here is the sample for [Abstract Class] -> [Class] without the Interface
Abstract class BaseData
{
protected $connection;
public function __construct($connection)
{
$this->connection = $connection;
}
abstract public function connected();
abstract public function get();
}
class UserData extends BaseData
{
public function exists()
{
return is_connected($this->connection);
}
public function get()
{
return get_data($this->connection);
}
}
$oUserData = new UserData(new Connection());
I am currently creating a small app (might grow larger) and confused on how to implement in the beginning correctly.
By the way, is this declaration for __construct() with parameter make sense in Interface?
public function __construct($connection);
Abstract classes defines an interface that must be implemented to the heirs of the abstract class. An Interface-Construct defines an interface that must be implemented by a class that implements the interface-construct, the implementation of the interface is not limited to a single interface, whereas class inheritance is coupled to a single (abstract) class.
Interfaces in PHP are intentionally used to allow typehints of an limited subset of an entire class interface. There is no reason for an interface on abstract classes aslong their receiver of instances of their heirs did not use them ( with typehinting or logical identification over instanceof / is_a ). The more valuable benefit of interface-constructs are the possibility of replacing an common implementation of an interfaces with a alternate implementation.
In case of your BaseData-Example, i recommend to drop the abstract idea and use a trait and seperate interfaces instead.
trait connectionBrokerConstructor {
protected $connection;
public function isConnected()
{
return $this->connection instanceof Connection;
}
public function setConnection(Connection $connection)
{
$this->connection = $connection;
}
}
interface connectable
{
public function setConnection(Connection $connection);
public function isConnected();
}
interface userDataRepositoryInterface
{
public function get();
}
class UserData implements connectable, userDataRepositoryInterface
{
use connectionBrokerConstructor;
public function __construct(Connection $connect = null)
{
$this->setConnection($connection);
}
public function get()
{
return array('something');
}
}
Really abstract classes and interfaces are different.
Consider an interface as a contract, it lays out the rules that other classes (which implement it) must follow.
Abstract classes on the other hand are more like starting points, which other classes can build on, hence why they are sometimes called base classes.
------- Edit with example
I'm not an expert on such things, but I've always just done interface -> class.
For example, here is a simple interface:
interface AnimalInterface {
public function all();
public function findBySlug($slug);
}
And here is the class which implements that interface (simplified):
class AnimalEloquentRepository implements AnimalInterface {
public function all()
{
return Animal::all();
}
public function findBySlug($slug)
{
return Animal::whereSlug($slug)->first();
}
}
I do often have a base class, which others extend, but I've only once used an abstract class in a real world app, and that ended up getting replaced.
I'm sure there are better ways to do things, but this has worked really well for me in the past.
My reputation doesn't allow comments, but this statement in tr0y's answer is misleading:
"Abstract classes defines an interface that must be implemented to the heirs of the abstract class."
One of the main differences between an interface and an abstract class is that you are not required to implement any of the methods of an abstract class in a class that extends it. It's quite common for the abstract class to have methods with default behavior and only provide those methods in the heirs if the default behavior is not what you want.
On the other hand, you are require to create all methods specified in an interface in any class that implements that interface.
Another difference is that methods in an interface cannot have a body, while methods in an abstract class must have a body.
Related
I have an abstract class that declares the methods required to its children. It also has a construstor that its children inherits. How can I make the abstract class affect the children of the classes that extends it. To further clarify my question, here is my case:
The Abstract Class (abstract.php):
<?php
include_once 'database.php';
include_once 'validation.php';
abstract class DataOperations extends DatabaseConnection {
//The error string shared by all children of DataOperations
//This will be the message to be displayed in case validation failure
public $validator;
public $err_valid_string;
/**
* The DataOperations' constructor ensures that all of its children can perform database operation
* by automatically starting it for them. In case a child overrides this constructor, this child
* must explicitly start the connection to prevent fatal errors. Also, $validator must be re-instantiated
*/
public function __construct() {
$this->startDBConnection();
$this->validator = new InputValidator();
}
public function __destruct() {
}
abstract public function validateData();
abstract public function loadRecord($key, $cascade);
abstract public function saveRecord();
abstract public function updateRecord();
abstract public function deleteRecord();
}
?>
Now, here is the child object that extends the DataOperations abstract class
class Guest extends DataOperations {
//some properties here
public function validateData() {
//implementation
}
public function newRecord(implementation) {
//implementation
}
public function loadRecord($key, $cascade){
//implementation
}
public function saveRecord() {
//implementation
}
public function updateRecord() {
//implementation
}
public function deleteRecord() {
//implementation
}
}
?>
And here is another class, which is a child of Guest
class Booking extends Guest {
//some properties here
public function validateData() {
//implementation
}
public function newRecord(implementation) {
//implementation
}
public function loadRecord($key, $cascade){
//implementation
}
public function saveRecord() {
//implementation
}
public function updateRecord() {
//implementation
}
public function deleteRecord() {
//implementation
}
}
?>
The problem is, if I remove a method in Booking, say deleteRecord(), PHP won't throw an error because I think abstract class doesn't affect its 'grandchildren'. How can I fix this? I thought of using interfaces but my system already has 11 classes that depends to some methods of the abstract class. It will require intensive refactoring.
As you himself stated interface is best suited solution. Like
include_once 'database.php';
include_once 'validation.php';
interface DbInterface {
abstract public function validateData();
abstract public function loadRecord($key, $cascade);
abstract public function saveRecord();
abstract public function updateRecord();
abstract public function deleteRecord();
}
class DataOperations extends DatabaseConnection {
//The error string shared by all children of DataOperations
//This will be the message to be displayed in case validation failure
public $validator;
public $err_valid_string;
/**
* The DataOperations' constructor ensures that all of its children can perform database operation
* by automatically starting it for them. In case a child overrides this constructor, this child
* must explicitly start the connection to prevent fatal errors. Also, $validator must be re-instantiated
*/
public function __construct() {
$this->startDBConnection();
$this->validator = new InputValidator();
}
public function __destruct() {
}
}
class Guest extends DataOperations implements DbInterface {
- - -
}
class Booking extends Guest implements DbInterface {
- - -
}
First as you see I removed abstract from parent class as I assuming only those methods are abstract. Second as per your problem of 11 classes depend on Abstract class, I would say As you only remove abstract methods, Class implementing abstract methods now should implement interface. It is one time needed task. While classes using other normal methods of abstract class work like previous.
The best and cleanest way would be to have your "BOOKING" class extend the "DATAOPERATIONS" class, instead of GUEST, because looks like you don't have any extra methods in the BOOKING class. other wise make and interface and implement it. That is not the preferred way but you would have to give more info your situation.
To be clear, re-declaring a method in a child class will overwrite the parent class's implementation of that method when called from the child class, while not affecting any additional functionality provided by extending the parent class:
class a
{
function hello()
{
echo "Hello";
}
function goodbye()
{
echo "Goodbye";
}
}
/**
* class b overwrites class a's implementation of method goodbye but will retain
* it's definition for method hello
*/
class b extends a
{
function goodbye()
{
echo "See ya!";
}
}
$object = new b();
$object->hello(); // Hello
$object->goodbye();// See ya!
It appears that you want to implement a consistent interface across multiple class definitions. If this is the case, you will likely want to explore using PHP's interfaces.
These allow you to specify the methods that must exist in your class definition along with their set of arguments (collectively known as the signature). Your class definitions will implement an interface and if your definition does not meet the interface implementation specification, a fatal error will be thrown.
From the PHP manual:
// Declare the interface 'iTemplate'
interface iTemplate
{
public function setVariable($name, $var);
public function getHtml($template);
}
// Implement the interface
// This will work
class Template implements iTemplate
{
private $vars = array();
public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
public function getHtml($template)
{
foreach($this->vars as $name => $value) {
$template = str_replace('{' . $name . '}', $value, $template);
}
return $template;
}
// This will not work
// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (iTemplate::getHtml)
class BadTemplate implements iTemplate
{
private $vars = array();
public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
}
You can find more information about interface in the PHP manual:
http://us2.php.net/interface
Finally, it looks like you are hoping to define a common constructor for the child classes. Your child classes can both extend the DataOperations class while implementing a separate interface:
class Guest extends DataOperations implements DatabaseWriter
...
I'm trying to decide the design pattern for a class structure I'm working with and I'm torn on the best way to implement the setup of the classes.
One approach calls an abstract setup function in the constructor of the abstract class, the other is to override the constructor in the classes which extend the abstract class.
A couple of (contrived and simplified) examples to outline my thinking:
Calling abstract method
<?php
abstract class VehicleAbstract implements VehicleInterface
{
protected $_wheels;
private $_engine;
public function __construct(EngineInterface $engine)
{
$this->setupWheels();
$this->_engine = $engine;
$this->_engine->setWheelsToDrive($this->_wheels);
}
public abstract function setupWheels();
}
class Car extends VehicleAbstract
{
public function setupWheels()
{
$this->_wheels = array(
"frontL",
"frontR",
"backL",
"backR"
);
}
}
Pros:
When implementing the concrete class it's obvious the method
"setupWheels" needs to be created.
Only the setup code needs to be written inside the "setupWheels"
method.
Cons:
When implementing it may not be immediately obvious what
"setupWheels" needs to do without looking through the parent class.
Someone new looking at the extended class may not realise the method
is called when the class is created.
Overriding constructor
<?php
abstract class VehicleAbstract implements VehicleInterface
{
protected $_wheels;
private $_engine;
public function __construct(EngineInterface $engine)
{
$this->_engine = $engine;
$this->_engine->setWheelsToDrive($this->_wheels);
}
}
class Car extends VehicleAbstract
{
public function __construct(EngineInterface $engine)
{
$this->_wheels = array(
"frontL",
"frontR",
"backL",
"backR"
);
parent::__construct($engine);
}
}
Pros:
When viewing the concrete class immediately obvious when the wheel data is being setup.
Cons:
When extending the abstract class it may be missed that the wheel
data needs to be setup at all.
While implementing the new constructor need to remember to call the
parent constructor.
Need to call parent constructor in correct position in new constructor.
Here is an example of my class structure for a data mapping pattern (simplified). Notice that the save and find methods are technically implemented in the concrete class, but do not do anything yet. What alternatives are there to avoid this? One option I am currently using is an abstract DataMapperAbstract class that implements the interface, throws an exception for every method, then all concrete data mappers only have to implement the functions they use - it just smells bad. Personally, I have thought of creating a separate interface for each method (DataMapper_FindInterface, DataMapper_SaveInterface, DataMapper_DeleteInterface, etc.) but it seems a bit smelly.
interface DataMapperInterface
{
public function find($params);
public function save($object);
public function delete($object);
}
class DataMapper_User implements DataMapperInterface
{
public function find($params)
{
//Execute code to retrieve data from data source
return someDataRetrievalMethod($params);
}
public function save($object)
{
throw new Exception('Method not yet implemented.');
}
public function delete($object)
{
throw new Exception('Method not yet implemented.');
}
}
As long as you are not in the class that has al methods implement, make the class abstract.
Abstract classes can not be instantiated, and there must be another class thats extends the abstract class with a implementation.
So your code so far would look like this:
interface DataMapperInterface
{
public function find($params);
public function save($object);
public function delete($object);
}
abstract class DataMapper_User implements DataMapperInterface
{
public function find($params)
{
//Execute code to retrieve data from data source
return someDataRetrievalMethod($params);
}
}
What is implementing a function? normally, what I know is implementing an interface which has
function foo();
and implementing like
function foo($bar)
in another class
but what happens when I implement the function in the interface? do I have to reimplement them in the subclasses? or can I use them in subclasses directly, assuming they are implemented in the subclasses.
interface ibarbar{
function foo($bar)
{
return $bar.$bar;}
}
class barbar implements ibarbar
{
function baz()
{
$this->barbar(); //used without implementing in subclass. expected results unknown.
}
}
PHP documentation says
// This will not work
// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (iTemplate::getHtml)
class BadTemplate implements iTemplate
{
private $vars = array();
public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
}
so all methods in an interface are abstract methods. but I couldn't find how to extend a function. or implement a function
You can't implement a function in an interface. You can only specify its signature.
If you want to specify signatures for some methods but provide implementation for others, use an abstract class:
abstract class A {
abstract public function B($c);
public function C($d) {
// do something
}
}
class B extends A {
public function B($c) { // need to implement B, as it is abstract
$this->C($c); // but can directly use C, as it is not
}
}
An interface has no implementation, by definition.
You're talking inheritance, here, if you have a function having an implementation that you override / Shadow in another class.
In PHP, can I specify an interface to have fields, or are PHP interfaces limited to functions?
<?php
interface IFoo
{
public $field;
public function DoSomething();
public function DoSomethingElse();
}
?>
If not, I realize I can expose a getter as a function in the interface:
public GetField();
You cannot specify members. You have to indicate their presence through getters and setters, just like you did. However, you can specify constants:
interface IFoo
{
const foo = 'bar';
public function DoSomething();
}
See http://www.php.net/manual/en/language.oop5.interfaces.php
Late answer, but to get the functionality wanted here, you might want to consider an abstract class containing your fields. The abstract class would look like this:
abstract class Foo
{
public $member;
}
While you could still have the interface:
interface IFoo
{
public function someFunction();
}
Then you have your child class like this:
class bar extends Foo implements IFoo
{
public function __construct($memberValue = "")
{
// Set the value of the member from the abstract class
$this->member = $memberValue;
}
public function someFunction()
{
// Echo the member from the abstract class
echo $this->member;
}
}
There's an alternative solution for those still curious and interested. :)
Use getter setter. But this might be tedious to implement many getters and setters in many classes, and it clutter class code. And you repeat yourself!
As of PHP 5.4 you can use traits to provide fields and methods to classes, ie:
interface IFoo
{
public function DoSomething();
public function DoSomethingElse();
public function setField($value);
public function getField();
}
trait WithField
{
private $_field;
public function setField($value)
{
$this->_field = $value;
}
public function getField()
{
return $this->field;
}
}
class Bar implements IFoo
{
use WithField;
public function DoSomething()
{
echo $this->getField();
}
public function DoSomethingElse()
{
echo $this->setField('blah');
}
}
This is specially usefull if you have to inherit from some base class and need to implement some interface.
class CooCoo extends Bird implements IFoo
{
use WithField;
public function DoSomething()
{
echo $this->getField();
}
public function DoSomethingElse()
{
echo $this->setField('blah');
}
}
Interfaces are only designed to support methods.
This is because interfaces exist to provide a public API that can then be accessed by other objects.
Publicly accessible properties would actually violate encapsulation of data within the class that implements the interface.
You cannot specify properties in an interface : only methods are allowed (and make sense, as the goal of an interface is to specify an API)
In PHP, trying to define properties in an interface should raise a Fatal Error : this portion of code :
interface A {
public $test;
}
Will give you :
Fatal error: Interfaces may not include member variables in...