热搜:NVER node 开发 php

问个子类对象直接调用基类内被重载的函数的问题?

2024-09-14 11:40:01
问个子类对象直接调用基类内被重载的函数的问题?

/// 问题看如下代码
<?php
class A
{
function A()

$this->nNum = 1024;
}
function SelfClass()
{
echo "class A
";
}
}

class B extends A
{
function SelfClass()
{
echo "class B
";
}
}
?>

<?php
$obj = new B();
$obj->SelfClass(); // 调用B类的函数SelfClass()函数
/* 如何能使用对象obj的基类的SelfClass()函数?
C++下可以写类似的代码$obj->A::SelfClass(),那么PHP可以如何实现呢?*/
?>


回复讨论(解决方案)

我所求的并非类似这种答案
class B extends A
{
function SelfClass()
{
echo "class B
";
}

function SelfClassX()
{
parent::SelfClass();
}
}

php没有提供这样的语法,不过可以模拟一下,但是不是很推荐这样用

<?phpclass A{	function A()	{ 		$this->nNum = 1024;	}	function SelfClass()	{		echo "class A
" . $this->nNum . "
"; } function __call($name, $arguments) { list($class_name, $function_name) = explode('_', $name); if(is_subclass_of($this, $class_name)) { if ($class_name == __CLASS__) { self::$function_name(); } else { $class_name::$function_name(); } } }}class B extends A{ function B() { $this->nNum = 2048; } function SelfClass() { echo "class B
" . $this->nNum . "
"; } }class C extends B{ function C() { $this->nNum = 4096; } function SelfClass() { echo "class C
" . $this->nNum . "
"; } }$obj = new B();$obj->SelfClass(); // 调用B类的函数SelfClass()函数$obj->A_SelfClass();$obj = new C();$obj->SelfClass(); // 调用C类的函数SelfClass()函数$obj->A_SelfClass();$obj->B_SelfClass();

这种语法$class_name::$function_name();编不过。
而且self::$function_name();的使用前提是$function_name()是静态函数。

<?php/// 折中地写了个实现,不完善,因为当C类继承B类时无法动态实现类的判断,语法不允许只能写硬代码类似于(A::$function_name(),B::$function_name())。class A{    function A()    {         $this->nNum = 1024;    }    function SelfClass()    {        echo "class A
" . $this->nNum . "
"; } function __call($name, $arguments) { list($class_name, $function_name) = explode('_', $name); if(method_exists($this, $function_name) && is_a($this, $class_name)) { if(is_subclass_of($this, $class_name)) { A::$function_name(); } else { $this->$function_name(); } } }} class B extends A{ function B() { $this->nNum = 2048; } function SelfClass() { echo "class B
" . $this->nNum . "
"; } }$obj = new B();$obj->B_SelfClass(); // 调用B类的SelfClass()函数$obj->A_SelfClass(); // 调用A类的SelfClass()函数

不太明白你这么做的意义
但至少 21 行的 A::$function_name();
应写作 $class_name::$function_name();
否则就不具普遍性了

$class_name::$function_name();这写法是有语法错误的。你不可以这样子写啊。
$class_name只能解析为字符串,无法使用这种语法。你想法是美好的但实现不了

这可不只是美好的愿望!实测证明写作 $class_name::$function_name() 是正确的(php5.4.12)

但需要注意的是:
无论是写作 $class_name::$function_name()
还是写作 A::$function_name()
都是不符合 php 语法的,因为需要 $function_name 是静态方法,而这里的不是

而在这里 php 没报错,显然是一个 BUG

对你的提出的写法我这边的测试环境没法实现,而且你说不行的,我这边能测试通过。
我实测过A::$function_name()是可以的,这个调用并不需要 $function_name 是静态方法。
而且$class_name::$function_name()这种写法我测过是无法把$class_name解析为类来用的
只能解析为字符串。难道是我的PHP版本太老了!!!

A::SelfClass(); //Strict Standards: Non-static method A::SelfClass() should not be called statically 这是正常的语法错(可屏蔽)
$function_name = 'SelfClass';
A::$function_name(); //这里不报语法错是不正常的

在一个系统里是不应该存在双重标准的!

我的是PHP Version 5.2.6

我在一本书上找到了A::$function_name();类似这个语法的用例

这段出自《PHP与MySQL程序设计》第4版

类名::方法名 这种写法古来有之,这是到了 php5.3 才开始有了限制

我之前用的都是C++,学习PHP时总是惯性认为某些用法应该差不多。

C++是编译执行的,所以源码被扫描几遍都无所谓
php是解释执行的,多扫描一遍都会影响执行效率

如果你自己去写解释器,你就会发现有很多二义性问题在二遍扫描中都无法解决

版主提到二义性问题确实是重点。想问一下版主,我原来是做C++游戏开发的,想改行做网站
作为一个PHP程序员的话,需不需要学习javascript,而基础html的话要学习到什么程度。

直接使用反射吧,php5.2 php5.3 都可以测试通过

<?phpclass A{	function A()	{ 		$this->nNum = 1024;	}	function SelfClass()	{		echo "class A
" . $this->nNum . "
"; } function __call($name, $arguments) { list($class_name, $function_name) = explode('_', $name); if(is_subclass_of($this, $class_name)) { //反射一个方法 $reflectionMethod = new ReflectionMethod($class_name, $function_name); // 使用当前对象调用 $reflectionMethod->invoke($this); } }}class B extends A{ function B() { $this->nNum = 2048; } function SelfClass() { echo "class B
" . $this->nNum . "
"; } }class C extends B{ function C() { $this->nNum = 4096; } function SelfClass() { echo "class C
" . $this->nNum . "
"; } }$obj = new B();$obj->SelfClass(); // 调用B类的函数SelfClass()函数$obj->A_SelfClass();$obj = new C();$obj->SelfClass(); // 调用C类的函数SelfClass()函数$obj->A_SelfClass();$obj->B_SelfClass();

那么参数传递呢?

发射方法确是好思路,但参数问题较为麻烦。

我想大概可以用evla()函数来解决吧

写错了,应该为void eval(string code_str);

那么参数传递呢?

没有那么麻烦
<?php
class A
{
function A()

$this->nNum = 1024;
}
function SelfClass($a,$b,$c,$d,$e,$f)
{

echo "class A
" . $this->nNum . "
" . "$a,$b,$c,$d,$e,$f". "
";
}

function __call($name, $arguments) {
list($class_name, $function_name) = explode('_', $name);

if(is_subclass_of($this, $class_name))
{
//反射一个方法
$reflectionMethod = new ReflectionMethod($class_name, $function_name);

// 使用当前对象调用
$reflectionMethod->invokeArgs($this, $arguments);
}


}
}

class B extends A
{
function B()
{
$this->nNum = 2048;
}
function SelfClass()
{
echo "class B
" . $this->nNum . "
";
}
}

class C extends B
{
function C()
{
$this->nNum = 4096;
}
function SelfClass()
{
echo "class C
" . $this->nNum . "
";
}
}

$obj = new B();
$obj->SelfClass(); // 调用B类的函数SelfClass()函数

$obj->A_SelfClass(1,2,3,4,5,6,7);

$obj = new C();
$obj->SelfClass(); // 调用C类的函数SelfClass()函数

$obj->A_SelfClass(1,2,3,4,5,6,7);
$obj->B_SelfClass();

喔,确实是很好地解决了。感谢hnxxwyq