网上很多讲义PHP面向对象:PHP中的多态2010-07-07多态这个概念,在Java中指的是变量可以指向的对象的类型,可是变量声明类型的子类。对象一旦创建,它的类型是不变的,多态的是变量。在PHP5中,变量的类型是不确定的,一个变量可以指向任何类型的数值、字符串、对象、资源等。我们无法说PHP5中多态的是变量。我们只能说在PHP5中,多态应用在方法参数的类型提示位置。一个类的任何子类对象都可以满足以当前类型作为类型提示的类型要求。所有实现这个接口的类,都可以满足以接口类型作为类型提示的方法参数要求。简单的说,一个类拥有其父类、和已实现接口的身份。 通过实现接口实现多态下面的例子中,UserAdmin类的静态方法,要求一个User类型的参数。在后面的使用中,传递了一个实现了User接口的类NormalUser的实例。代码成功运行。<? interface User{ // User接口 public function getName(); public function setName($_name); }class NormalUser implements User { // 实现接口的类. private $name; public function getName(){ return $this->name; } public function setName($_name){ $this->name = $_name; } }class UserAdmin{ //操作. public static function ChangeUserName(User $_user,$_userName){ $_user->setName($_userName); } }$normalUser = new NormalUser(); UserAdmin::ChangeUserName($normalUser,"Tom");//这里传入的是 NormalUser的实例. echo $normalUser->getName(); ?>程序运行结果:Tom通过继承关系实现多态下面是类和子类的关系。<? class User{ // User接口 public function getName(){} }class NormalUser extends User { // 继承自User类 private $name; public function getName(){ return $this->name; } public function setName($_name){ $this->name = $_name; } }class UserAdmin{ //操作. public static function ChangeUserName(User $_user,$_userName){ $_user->setName($_userName); } }$normalUser = new NormalUser(); UserAdmin::ChangeUserName($normalUser,"Tom");//这里传入的是 NormalUser的实例. echo $normalUser->getName(); ?>程序运行结果:Tom
第二个例子有点疑惑,假如改一下代码 NormalUser 增加一个方法sayhelloclass NormalUser extends User { // 继承自User类 private $name; public function getName(){ return $this->name; } public function setName($_name){ $this->name = $_name; } /*此处为测试新增*/ public function sayHello($_name) { echo 'hello: ' . $_name; } }在UserAdmin的ChangeUserName方法中加入一句$_user->sayHello($_userName),请问sayHello方法可以正确调用吗?class UserAdmin{ //操作. public static function ChangeUserName(User $_user,$_userName){ $_user->setName($_userName); $_user->sayHello($_userName); } }
//定义接口InterA interface InterA { void fun(); } //实现接口InterA的类B class B implements InterA { public void fun() { System.out.println(“This is B”); } } //实现接口InterA的类C class C implements InterA { public void fun() { System.out.println(“This is C”); } } class Test { public static void main(String[] args) { InterA a; a= new B(); a.fun(); a = new C(); a.fun(); } } 我说的就是InterA a
JAVA://定义接口Animal interface Animal { void Talk(); } //实现接口Animal的Dog class Dog implements Animal { public void Talk() { System.out.println("WongWong"); } } //实现接口Animal的类Cat class Cat implements Animal { public void Talk() { System.out.println("Miao"); } } class Test { public static void main(String[] args) { Animal a; a= new Dog(); a.Talk(); a = new Cat(); a.Talk(); } } PHP: <?php //定义接口Animal interface Animal { public function Talk(); } //实现接口Animal的Dog class Dog implements Animal { public function Talk() { echo("WongWong"); } } //实现接口Animal的类Cat class Cat implements Animal { public function Talk() { echo("Miao"); } } $a = new Dog(); $a->Talk(); $a = new Cat(); $a->Talk(); ?> 瞧他们多像啊,不能因为我类型弱就说我不够多态啊。
通过实现接口实现多态下面的例子中,UserAdmin类的静态方法,要求一个User类型的参数。在后面的使用中,传递了一个实现了User接口的类NormalUser的实例。代码成功运行。<?
interface User{ // User接口
public function getName();
public function setName($_name);
}class NormalUser implements User { // 实现接口的类.
private $name;
public function getName(){
return $this->name;
}
public function setName($_name){
$this->name = $_name;
}
}class UserAdmin{ //操作.
public static function ChangeUserName(User $_user,$_userName){
$_user->setName($_userName);
}
}$normalUser = new NormalUser();
UserAdmin::ChangeUserName($normalUser,"Tom");//这里传入的是 NormalUser的实例.
echo $normalUser->getName();
?>程序运行结果:Tom通过继承关系实现多态下面是类和子类的关系。<?
class User{ // User接口
public function getName(){}
}class NormalUser extends User { // 继承自User类
private $name;
public function getName(){
return $this->name;
}
public function setName($_name){
$this->name = $_name;
}
}class UserAdmin{ //操作.
public static function ChangeUserName(User $_user,$_userName){
$_user->setName($_userName);
}
}$normalUser = new NormalUser();
UserAdmin::ChangeUserName($normalUser,"Tom");//这里传入的是 NormalUser的实例.
echo $normalUser->getName();
?>程序运行结果:Tom
第二个例子有点疑惑,假如改一下代码
NormalUser 增加一个方法sayhelloclass NormalUser extends User { // 继承自User类
private $name;
public function getName(){
return $this->name;
}
public function setName($_name){
$this->name = $_name;
}
/*此处为测试新增*/
public function sayHello($_name) {
echo 'hello: ' . $_name;
}
}在UserAdmin的ChangeUserName方法中加入一句$_user->sayHello($_userName),请问sayHello方法可以正确调用吗?class UserAdmin{ //操作.
public static function ChangeUserName(User $_user,$_userName){
$_user->setName($_userName);
$_user->sayHello($_userName);
}
}
http://www.soft6.com/tech/16/169232.html
http://www.cnblogs.com/ihacklog/archive/2011/08/02/understanding-and-applying-polymorphism-in-php.html
怎么放狗,是指google的意思吗? (汗)
它使用了 interface (接口),肯定是多态了
其实不使用接口,也一样实现多态
多态是除封装和继承之外的另一个面向对象的三大特性之一,我个人看来PHP 中虽然可以实现多态,但和C++还有Java 这些面向对象的语言相比,多态性并不是那么突出 多态的应用
多态是除封装和继承之外的另一个面向对象的三大特性之一,我个人看来PHP 中虽然可以实现多态,但和C++还有Java 这些面向对象的语言相比,多态性并不是那么突出,因为PHP本身就是一种弱类型的语言,不存在父类对象转化为子类对象或者是子类对象转化为父类对象的问题,所以多态的应用并不是那么的明显;所谓多态性是指一段程序能够处理多种类型对象的能力,比如说在公司上班,每个月财务发放工资,同一个发工资的方法,在公司内不同的员工或是不同职位的员工,都是通过这个方法发放的,但是所发的工资都是不相同的。 所以同一个发工资的方法就出现了多种形态。对于面向对象的程序来说,多态就是把子类对象赋值给父类引用,然后调用父类的方法,去执行子类覆盖父类的那个方法,但在PHP 里是弱类型的,对象引用都是一样的不分父类引用,还是子类引用。
我们现在来看一个例子,首先还是要使用多态就要有父类对象和子类对象的关系。做一个形状的接口或是抽象类做为父类,里面有两个抽象方法,一个求周长的方法,另一个是求面积的方法;这接口的子类是多种不同的形状,每个形状又都有周长和面积,又因为父类是一个接口,所以子类里面就必须要实现父类的这两个周长和面积的抽象方法,这样做的目的是每种不同形状的子类都遵守父类接口的规范,都要有求周长和求面积的方法。 代码如下:<?
//定义了一个形状的接口,里面有两个抽象方法让子类去实现
interface Shape{
function area();
function perimeter();
}
//定义了一个矩形子类实现了形状接口中的周长和面积
class Rect implements Shape{
private $width;
private $height;
function __construct($width, $height){
$this->width=$width;
$this->height=$height;
}
function area(){
return "矩形的面积是:".($this->width*$this->height);
}
function perimeter(){
return "矩形的周长是:".(2*($this->width+$this->height));
}
}
//定义了一个圆形子类实现了形状接口中的周长和面积
class Circular implements Shape{
private $radius;
function __construct($radius){
$this->radius=$radius;
}
function area(){
return "圆形的面积是:".(3.14*$this->radius*$this->radius);
}
function perimeter(){
return "圆形的周长是:".(2*3.14*$this->radius);
}
}
//把子类矩形对象赋给形状的一个引用
$shape=new Rect(5, 10);
echo $shape->area()."<br>";
echo $shape->perimeter()."<br>";
//把子类圆形对象赋给形状的一个引用
$shape=new Circular(10);
echo $shape->area()."<br>";
echo $shape->perimeter()."<br>";
?> 上例执行结果:
执行结果
矩形的面积是:50
矩形的周长是:30
圆形的面积是:314
圆形的周长是:62.8 通过上例我们看到,把矩形对象和圆形对象分别赋给了变量$shape,调用$shape 引用中的面积和周长的方法,出现了不同的结果,这就是一种多态的应用,其实在我们PHP 这种弱类形的面向对象的语言里面,多态的特性并不是特别的明显,其实就是对象类型变量的变项应用。
二是从语法上保证作为接口的方法一定会被定义,当不使用 interface 时,就需要自行保证了
但是,$shape这个变量, 他=new Rect之后,
你一样可以看作它interface Shape的一个引用啊在c++里,只不过一个指针变量显式地定义了它指向了父类,你就觉得它一直指向父类的引用,
但实际上在运行时,它一样是指向了某个子类啊换句话说,你把$shape这个变量看作一个interface Shape的指针,然后它在运行时指向了该interface的不同实现,那不就一样了吗?欢迎继续讨论
怎么能看成是interface Shape的指针呢,"看成",不能是看成啊,代码怎么实现?
我这里对多态的理解基本是基于wiki百科上的描述
http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming
这篇科普文有概念描述,有设计目的,有举例,比如c++的操作符重载,+号碰到integer类型的就是数学概念上的相加,碰到chars类型的就是字符串拼接,这就是同一个符号+表现出多种操作形态。下面还有java,python的例子,php怎么就算不支持呢?
多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自“Delphi4 编程技术内幕”)。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。多态性在Object Pascal和C++中都是通过虚函数(Virtual Function) 实现的。你仔细看这句话:允许将子类类型的指针赋值给父类类型的指针, php允许吗? php是弱类型的根本不存在这么一说.
而且我在你引用百度百科解释里还有一句话
在面向对象语言中,接口的多种不同的实现方式即为多态
你又怎么看?你认为php不支持接口设计吗?允许将子类类型的指针赋值给父类类型的指针
你不妨用C++的实现方式写出来,看php能不能做到类似的设计。
没说php有指针啊,引用有吧,
1.php中你可拿到一个接口类型的引用吗?
2.不用试了,php做不到,只能做到接口的实现类的引用,或者是拿子类的引用
拿接口的实现类引用或子类的引用 调用自己的方法就叫多态吗?(这跟没有接口的调用有什么区别?)
那就是接口实现方法和方法重载以及方法覆盖的区别了,这对于所有语言都是一样的吧。
这个我贴的那个wiki页面正好有说到。
所以你意思是拿父类/接口的引用调用自己的方法才叫多态?
我给你的维基链接里有个java/python的例子,你认为那个能证明java/python支持多态不?
还有弱类型语言本身类型就是隐性多态的,所以你在php可以strlen(1)得到结果1.
你所谓的php拿接口类型的引用是个啥意思
我觉得最好不要陷入语法层来讨论设计层问题。
或者最好是你写个简单php例子来说明自己的论点,这样大家不会把时间浪费在对语义的理解上,而且中文对于国外技术名词的解释有时候实在不知道怎么理解好,还不如自己去啃英文理解得快。
//定义接口InterA
interface InterA
{
void fun();
}
//实现接口InterA的类B
class B implements InterA
{
public void fun()
{
System.out.println(“This is B”);
}
}
//实现接口InterA的类C
class C implements InterA
{
public void fun()
{
System.out.println(“This is C”);
}
}
class Test
{
public static void main(String[] args)
{
InterA a;
a= new B();
a.fun();
a = new C();
a.fun();
}
} 我说的就是InterA a
按照你给的java代码,InterA a;是强类型实现多态的方式,没办法,每个变量都有类型,而且事先就要定义类型,这都没问题,最重要的是这段代码核心的东西我觉得是,a始终是InterA类型,但是可以拥有B的特性,也可以拥有C的特性,同一个物件可以以多种形态出现,这叫多态。但是弱类型的php实现方式不是这样,你赋什么类型给一个变量,那么变量当前就是这个类型。我觉得这个属于"茴"字有几种写法的问题,属于语法层,真正重要的多态可以让你实现什么样的设计,你为什么觉得php满足不了。有人用C都可以OOP呢。
interface Animal
{
void Talk();
}
//实现接口Animal的Dog
class Dog implements Animal
{
public void Talk()
{
System.out.println("WongWong");
}
}
//实现接口Animal的类Cat
class Cat implements Animal
{
public void Talk()
{
System.out.println("Miao");
}
}
class Test
{
public static void main(String[] args)
{
Animal a;
a= new Dog();
a.Talk();
a = new Cat();
a.Talk();
}
} PHP:
<?php
//定义接口Animal
interface Animal
{
public function Talk();
}
//实现接口Animal的Dog
class Dog implements Animal
{
public function Talk()
{
echo("WongWong");
}
}
//实现接口Animal的类Cat
class Cat implements Animal
{
public function Talk()
{
echo("Miao");
}
}
$a = new Dog();
$a->Talk();
$a = new Cat();
$a->Talk();
?>
瞧他们多像啊,不能因为我类型弱就说我不够多态啊。
希望更多人参与进来,咱们群P.
感觉LZ的帖子,能引起争论的帖子就是好帖子。
下面的例子中,UserAdmin类的静态方法,要求一个User类型的参数。
在后面的使用中,传递了一个实现了User接口的类NormalUser的实例。代码成功运行。
01
<?
02
interface User{ // User接口
03
public function getName();
04
public function setName($_name);
05
}
06
07
class NormalUser implements User { // 实现接口的类.
08
private $name;
09
public function getName(){
10
return $this->name;
11
}
12
public function setName($_name){
13
$this->name = $_name;
14
}
15
}
16
17
class UserAdmin{ //操作.
18
public static function ChangeUserName(User $_user,$_userName){
19
$_user->setName($_userName);
20
}
21
}
22
23
$normalUser = new NormalUser();
24
UserAdmin::ChangeUserName($normalUser,"Tom");//这里传入的是 NormalUser的实例.
25
echo $normalUser->getName();
26
?>
程序运行结果:
1
Tom
通过继承关系实现多态
下面是类和子类的关系。
01
<?
02
class User{ // User接口
03
public function getName(){}
04
}
05
06
class NormalUser extends User { // 继承自User类
07
private $name;
08
public function getName(){
09
return $this->name;
10
}
11
public function setName($_name){
12
$this->name = $_name;
13
}
14
}
15
16
class UserAdmin{ //操作.
17
public static function ChangeUserName(User $_user,$_userName){
18
$_user->setName($_userName);
19
}
20
}
21
22
$normalUser = new NormalUser();
23
UserAdmin::ChangeUserName($normalUser,"Tom");//这里传入的是 NormalUser的实例.
24
echo $normalUser->getName();
25
?>
程序运行结果:
view sourceprint?
1
Tom
注意到前面还有 多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作
只要父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作就可以说是支持多态了class Animal {
var $voice = '未定义';
var $root;
function __construct() {
$this->root = $this;
}
function signal($o) {
$this->root = $o;
}
function Talk() {
echo $this->root->voice;
}
}class Cat extends Animal {
var $voice = '喵';
}class Dog extends Animal {
var $voice = '汪汪';
}$a = new Animal;
$a->Talk(); $a->signal(new Cat);
$a->Talk();$a->signal(new Dog);
$a->Talk();由于不习惯 php5 的格式,采用了 php4 的格式
增加一个类//注意没有继承自 Animal
class Pig {
var $voice = '哼';
}$a = new Animal;
$a->Talk(); $a->signal(new Cat);
$a->Talk();$a->signal(new Dog);
$a->Talk();
// 注意这句
$a->signal(new Pig);
$a->Talk();这算多态吗?
其实这个里面说的很清楚了,Subtype polymorphism is the ability to create a variable, a function, or an object that has more than one form. php能吗? 很显然是可以的
楼主却偏偏用红字突出了简化的不完整的描述....
abstract class A
{
abstract function show();
}class B extends A
{
function show(){
echo 'B';
}
}
$obj = new B();
$obj->show();
多继承过于复杂, 有副作用,
所以包括Java等语言都是用interface来部分实现...
什么叫多态?基类能调用派生类的方法就是多态,你管它强弱类型呢