PHP示例中的通用多态性
因为只有狗才能玩“取回”,这个例子是好主意还是坏主意?由于使用instanceof,我怀疑这是一个非常糟糕的主意,但我不完全确定原因PHP示例中的通用多态性,php,polymorphism,Php,Polymorphism,因为只有狗才能玩“取回”,这个例子是好主意还是坏主意?由于使用instanceof,我怀疑这是一个非常糟糕的主意,但我不完全确定原因 class Animal { var $name; function __construct($name) { $this->name = $name; } } class Dog extends Animal { function speak() { return "Woof, woof!"
class Animal {
var $name;
function __construct($name) {
$this->name = $name;
}
}
class Dog extends Animal {
function speak() {
return "Woof, woof!";
}
function playFetch() {
return 'getting the stick';
}
}
class Cat extends Animal {
function speak() {
return "Meow...";
}
}
$animals = array(new Dog('Skip'), new Cat('Snowball'));
foreach($animals as $animal) {
print $animal->name . " says: " . $animal->speak() . '<br>';
if ($animal instanceof Dog) echo $animal->playFetch();
}
本质上我想问的是:“所有子类应该有相同的接口,还是可以有不同的接口?”在本文中,讨论接口很有用 任何实现健谈界面的动物或人类(或外国人)都可以在需要健谈的环境中使用:
protected function makeItSpeak(Talkative $being) {
echo $being->speak();
}
这是一种正确使用的多态方法。你不在乎你在处理什么,只要它能说话()
如果Dog
s也可以玩fetch,那对他们来说是很好的。如果你想概括一下,也可以从接口的角度来考虑。也许有一天,你会得到一只训练有素的猫,它也会玩取回游戏
class Cog extends Cat implements Playfulness {
public function playFetch() { ... }
}
这里最重要的一点是,当你对某个东西调用playFetch()
时,这是因为你想和那个动物玩fetch。您不调用playFetch
,因为。。。你可以,但因为你想在这一刻玩打球。如果你不想玩fetch,那就别叫它了。如果您需要在特定情况下玩fetch,那么您需要可以玩fetch的东西。您可以通过接口声明来确保这一点
使用类继承可以实现同样的效果,只是灵活性较差。在存在刚性层次结构的某些情况下,尽管它非常有用:
abstract class Animal { }
abstract class Pet extends Animal { }
class Dog extends Pet {
public function playFetch() { ... }
}
class GermanShepherd extends Dog {
public function beAwesome() { ... }
}
然后,在某些特定的上下文中,您可能不需要任何可以执行某些操作(接口)的对象,但您特别需要一个GermanShepherd
,因为只有它才能令人敬畏:
protected function awesomeness(GermanShepherd $dog) {
$dog->beAwesome();
}
也许在这条路上你会创造出一种新的GermanShepherd
s,它也很棒,但是extend
theGermanShepherd
类。它们仍然可以使用awesomeness
函数,就像使用接口一样
你当然不应该做的是循环一堆随机的事情,检查它们是什么,让它们做自己的事情。这在任何情况下都不太合理。PHP中多态性的另一个例子
<?php
interface Shape {
public function getArea();
}
class Square implements Shape {
private $width;
private $height;
public function __construct($width, $height) {
$this->width = $width;
$this->height = $height;
}
public function getArea(){
return $this->width * $this->height;
}
}
class Circle implements Shape {
private $radius;
public function __construct($radius) {
$this->radius = $radius;
}
public function getArea(){
return 3.14 * $this->radius * $this->radius;
}
}
function calculateArea(Shape $shape) {
return $shape->getArea();
}
$square = new Square(5, 5);
$circle = new Circle(7);
echo calculateArea($square), "<br/>";
echo calculateArea($circle);
?>
几乎和你一样,克里希纳达斯,布拉德。本文帮助我理解了如何在PHP中处理多态性
<?php
interface Shape {
public function getArea();
}
class Square implements Shape {
private $width;
private $height;
public function __construct($width, $height) {
$this->width = $width;
$this->height = $height;
}
public function getArea(){
return $this->width * $this->height;
}
}
class Circle implements Shape {
private $radius;
public function __construct($radius) {
$this->radius = $radius;
}
public function getArea(){
return 3.14 * $this->radius * $this->radius;
}
}
function calculateArea(Shape $shape) {
return $shape->getArea();
}
$square = new Square(5, 5);
$circle = new Circle(7);
echo calculateArea($square), "<br/>";
echo calculateArea($circle);
?>
接口形状\u抽屉{
公共功能图(外形$obj);
}
类circle实现了shape\u抽屉{
公共功能图(外形$obj){
回显“绘图圆,区域:{$obj->Area}
”;
}
}
类square实现了形状_抽屉{
公共功能图(外形$obj){
echo“绘图方块,面积:{$obj->Area}
”;
}
}
类triangle实现了shape\u抽屉{
公共功能图(外形$obj){
echo“绘制三角形,区域:{$obj->Area}
”;
}
}
一流的造型工厂{
公共静态函数getShape(){
$shape=$_请求['shape'];
如果(类_存在($shape)){
返回新的$shape();
}
抛出新异常(“不支持的格式”);
}
}
阶级形态{
公共功能建筑(面积){
$this->area=$area;
}
公共功能图(外形图$obj){
返回$obj->draw($this);
}
}
$shape=新形状(50);
试一试{
$drawer=shape_工厂::getShape();
}
捕获(例外$e){
$drawer=新圆();
}
echo$shape->draw($drawer);
我很确定以前有人问过这个问题,但简单的回答是子类可以有不同的接口。我很确定第一个示例不正确,因为使用instanceof进行条件逻辑。多态性的全部目的不是为了不这样做吗?为什么你想让所有的动物都做些什么(说话),除了一种动物(狗)?听起来好像是错误的逻辑在循环中,而不是类定义。它们都在说话,包括狗。但是只有狗才能玩。不管怎样,我想我可能已经在这里找到了一些有用的东西:如果两个不同的对象可以用不同的方式做相同的事情,那就是多态性。如果一个对象还可以做其他事情,那么就这样吧。那不是多态行为,因为它是对象特有的行为。你就不会把那个特定的行为当作多态的。看到一个php开发人员谈论接口是令人耳目一新的。我在php中经常使用它们,但在大多数主要框架中都没有爱,因此普通php开发人员很少采用这种思想。@deceze回答得很好。但我想知道这些特征是否也值得在这里提及@Muhammad不是真的,依我看。特征不可识别,因此与讨论无关。我知道它很古老,但如果我的狗能“呼吸”、“行走”、“跳跃”,我的猫也能,这是否意味着我必须实现所有这些接口?那是很多工具,不是吗@Steve 1)实际上,您可能不会为这些方法中的每一个创建一个接口,而是创建一个接口,将所有三个方法定义在一起。这取决于您将接口细分为有意义的部分,既不太详细,也不太大和不相关。2) 您可以创建复合接口,例如,接口哺乳动物扩展呼吸、行走、跳跃
。
<?php
interface Shape {
public function getArea();
}
class Square implements Shape {
private $width;
private $height;
public function __construct($width, $height) {
$this->width = $width;
$this->height = $height;
}
public function getArea(){
return $this->width * $this->height;
}
}
class Circle implements Shape {
private $radius;
public function __construct($radius) {
$this->radius = $radius;
}
public function getArea(){
return 3.14 * $this->radius * $this->radius;
}
}
function calculateArea(Shape $shape) {
return $shape->getArea();
}
$square = new Square(5, 5);
$circle = new Circle(7);
echo calculateArea($square), "<br/>";
echo calculateArea($circle);
?>
interface shape_drawer{
public function draw(Shape $obj);
}
class circle implements shape_drawer{
public function draw(Shape $obj){
echo "Drawing Circle, Area: {$obj->area} <br>";
}
}
class square implements shape_drawer{
public function draw(Shape $obj){
echo "Drawing Square, Area: {$obj->area} <br>";
}
}
class triangle implements shape_drawer{
public function draw(Shape $obj){
echo "Drawing Triangle, Area: {$obj->area} <br>";
}
}
class shape_factory{
public static function getShape(){
$shape = $_REQUEST['shape'];
if(class_exists($shape)) {
return new $shape();
}
throw new Exception('Unsupported format');
}
}
class Shape{
public function __construct($area){
$this->area = $area;
}
public function draw(shape_drawer $obj) {
return $obj->draw($this);
}
}
$shape = new Shape(50);
try {
$drawer = shape_factory::getShape();
}
catch (Exception $e) {
$drawer = new circle();
}
echo $shape->draw($drawer);