是否可以在抽象类中指定必须由PHP中的具体实现实现的接口?
目前我们正在做类似以下的事情(希望简单到可以遵循):
<?php
declare(strict_types=1);
interface SensorObserver
{
public function sensorChanged( array $sensorData );
}
class SensorSubject
{
protected $observers = [];
public function addSensorObserver( SensorObserver $sensorObserver ) : bool
{
if ( !in_array( $sensorObserver, $this->observers ) )
{
$this->observers[] = $sensorObserver;
return true;
}
return false;
}
public function removeSensorObserver( SensorObserver $sensorObserver ) : bool
{
if ( !in_array( $sensorObserver, $this->observers ) )
{
return false;
}
else
{
unset( $this->observers[array_search( $sensorObserver, $this->observers )]);
return true;
}
}
public function notifyObservers( array $sensorData )
{
foreach( $this->observers as $observer )
{
$observer->sensorChanged( $sensorData );
}
}
}
abstract class GenericDisplay
{
protected $name;
protected $sensorData;
protected $displayData;
abstract public function showDisplay();
abstract protected function generateDisplayData();
public function __construct( string $name )
{
$this->name = $name;
$this->sensorData = [];
$this->displayData = [];
}
}
class DisplayDeviceA extends GenericDisplay implements SensorObserver
{
public function __construct()
{
parent::__construct( 'DisplayDeviceA' );
$this->sensorData = [ 'SensorTypeA' => 0.0, 'SensorTypeB' => 0.0 ];
$this->generateDisplayData();
}
public function showDisplay()
{
echo PHP_EOL . "{$this->name}: " . PHP_EOL;
foreach ( $this->displayData as $key => $value )
{
echo "{$key}: {$value}" . PHP_EOL;
}
}
protected function generateDisplayData()
{
// Complicated processing done for output here :)
$this->displayData = $this->sensorData;
}
public function sensorChanged( array $sensorData )
{
$dirtySensorData = false;
foreach( $sensorData as $key => $value )
{
if ( array_key_exists( $key, $this->sensorData ) )
{
// This is just an example, <imagine custom processing here when sensor data changes />,
// otherwise we could just implement in the base abstract class or perhaps with a trait
$this->sensorData[$key] = $value;
$dirtySensorData = true;
}
}
if ( $dirtySensorData )
{
$this->generateDisplayData();
}
}
}
class DisplayDeviceB extends GenericDisplay implements SensorObserver
{
public function __construct()
{
parent::__construct( 'DisplayDeviceB' );
$this->sensorData = [ 'SensorTypeA' => 0.0, 'SensorTypeB' => 0.0, 'SensorTypeC' => 0.0 ];
$this->generateDisplayData();
}
public function showDisplay()
{
echo PHP_EOL . "{$this->name}: " . PHP_EOL;
foreach ( $this->displayData as $key => $value )
{
echo "{$key} => {$value}" . PHP_EOL;
}
}
protected function generateDisplayData()
{
// Complicated processing done for output here :)
$this->displayData = $this->sensorData;
}
public function sensorChanged( array $sensorData )
{
$dirtySensorData = false;
foreach( $sensorData as $key => $value )
{
if ( array_key_exists( $key, $this->sensorData ) )
{
// Again, just an example...
$this->sensorData[$key] = $value;
$dirtySensorData = true;
}
}
if ( $dirtySensorData )
{
$this->generateDisplayData();
}
}
}
class DisplayDeviceC extends GenericDisplay implements SensorObserver
{
public function __construct()
{
parent::__construct( 'DisplayDeviceC' );
$this->sensorData = [ 'SensorTypeB' => 0.0, 'SensorTypeD' => 0.0 ];
$this->generateDisplayData();
}
public function showDisplay()
{
echo PHP_EOL . "{$this->name}: " . PHP_EOL;
foreach ( $this->displayData as $key => $value )
{
echo "{$key} --> {$value}" . PHP_EOL;
}
}
protected function generateDisplayData()
{
// Complicated processing done for output here :)
$this->displayData = $this->sensorData;
}
public function sensorChanged( array $sensorData )
{
$dirtySensorData = false;
foreach( $sensorData as $key => $value )
{
if ( array_key_exists( $key, $this->sensorData ) )
{
// Again, just an example...
$this->sensorData[$key] = $value;
$dirtySensorData = true;
}
}
if ( $dirtySensorData )
{
$this->generateDisplayData();
}
}
}
$testDisplays = [ new DisplayDeviceA(), new DisplayDeviceB(), new DisplayDeviceC() ];
foreach( $testDisplays as $display )
{
$display->showDisplay();
}
$sensorSubject = new SensorSubject();
foreach( $testDisplays as $display )
{
$sensorSubject->addSensorObserver( $display );
}
$sensorSubject->notifyObservers( ['SensorTypeB' => 10.0, 'SensorTypeD' => 5.0] );
foreach( $testDisplays as $display )
{
$display->showDisplay();
}
想知道是否有基本的写作方式:
interface SensorObserver
{
public function sensorChanged( array $sensorData );
}
abstract class GenericDisplay implements SensorObserver
{
...
abstract public function sensorChanged( array $sensorData );
...
}
class ConcreteDisplay extends GenericDisplay
{
public function sensorChanged( array $sensorData ) { ... };
}
感谢下面的@Mark Baker和@Pael Petrov。 如果有人偶然发现这个问题,那就是一个有效的例子:
<?php
interface AnInterface
{
public function foo();
}
abstract class AbstractClass implements AnInterface
{
//...
}
class ConcreteClass extends AbstractClass
{
public function foo()
{
echo 'foo';
}
}
$concrete = new ConcreteClass();
$concrete->foo();
答案 0 :(得分:1)
如果抽象类实现了一些接口具体类,则会自动实现抽象类的所有接口,因此您只需要扩展抽象类:
class ConcreteDisplay extends GenericDisplay
{
//implement interface methods here
//if not implemented in the parend class
}
这将完成工作