我在php中有以下代码:
<?php
interface someInterface {
public function foo();
}
class A implements someInterface {
public function foo(){
return [
'a' => 'some value',
'b' => 'some value',
'c' => [
'ca' => 'some value',
'cb' => 'some value',
'cc' => 'some value'
]
];
}
}
class B extends A {
public function foo(){
return [
'a' => 'some value 2',
'c' => [
'ca' => 'some value 3',
'cb' => 'some value 4'
]
];
}
}
执行以下操作
$b = new B();
var_dump($b->foo());
必须给我以下输出
[
'a' => 'some value 2',
'b' => 'some value',
'c' => [
'ca' => 'some value 3',
'cb' => 'some value 4',
'cc' => 'some value'
]
]
有谁知道如何实现这个目标?
任何人都可以延长class A
,我也不希望其他用户手动使用array_merge_recursive
来实现这一目标。
提前致谢
答案 0 :(得分:1)
你可以让中间的班级完成这项工作。它应该有另一个将被继承并随后使用的方法。这里唯一的条件是不在公开场合使用foo()
,而是getFoo()
而不是
interface someInterface {
public function foo();
}
class A implements someInterface {
public function foo(){
return [
'a' => 'some value',
'b' => 'some value',
'c' => [
'ca' => 'some value',
'cb' => 'some value',
'cc' => 'some value'
]
];
}
}
class Middle extends A {
public function getFoo() {
return array_merge_recursive(parent::foo(), $this->foo());
}
}
class B extends Middle {
public function foo(){
return [
'a' => 'some value 2',
'c' => [
'ca' => 'some value 3',
'cb' => 'some value 4'
]
];
}
}
$b = new B();
var_dump($b->getFoo());
这也可以通过foo()
受保护以及执行__call()
工作的神奇getFoo()
方法来实现。然后调用$b->foo()
会触发__call()
,从而导致合并parent
this
foo()
的上下文并将其吐出。
顺便说一下,数组合并递归不会产生你想要的完全相同的输出,无论如何,你可以在getFoo()
(或__call()
)中做你需要的任何逻辑
这里的问题可能是,如果foo()
的访问修饰符低于public
,则您无法在界面中拥有它。幸运的是,抽象类可能有抽象的受保护方法,这些方法将强制childred实现此方法。
__call()
方式和义务成员拥有protected foo()
的示例方案可能是:
abstract class Base {
abstract protected function foo();
}
abstract class A {
protected function foo(){
return [
'a' => 'some value',
'b' => 'some value',
'c' => [
'ca' => 'some value',
'cb' => 'some value',
'cc' => 'some value'
]
];
}
}
class Middle extends A {
public function __call($name, $args) {
if ($name == 'foo')
return array_merge_recursive(parent::foo(), $this->foo());
}
}
class B extends Middle {
protected function foo(){
return [
'a' => 'some value 2',
'c' => [
'ca' => 'some value 3',
'cb' => 'some value 4'
]
];
}
}
$b = new B();
var_dump($b->foo());
这样B
会自动完成foo的一些问题。
如果一个人不知道&#34; hack&#34;撰写$b->
时,不会收到foo()
的建议。
多一点黑客可以至少在Netbeans
和PHPStorm
在定义Middle
类之前注释foo()
有公共Middle
方法:
/**
* @method foo
*/
class Middle extends A {
稍后注释B
的实例实际上是Middle
的实例:
$b = new B();
/* @var $b Middle */
之后写$b->
会导致建议使用foo()
方法。
如果有另一个类继承B
并且没有方法但只有注释,那可能会更好,但据我所知,像B
这样的类将会从其他人那里编写而他们可能不会熟悉这个惯例。
答案 1 :(得分:0)
你可以试试这个:
<?php
interface someInterface
{
public function foo();
}
class A implements someInterface
{
public function foo()
{
return [
'a' => 'some value',
'b' => 'some value',
'c' => [
'ca' => 'some value',
'cb' => 'some value',
'cc' => 'some value'
]
];
}
}
class B extends A
{
public function foo()
{
$parent = parent::foo();
$arr = [
'a' => 'some value 2',
'c' => [
'ca' => 'some value 3',
'cb' => 'some value 4'
]
];
return $this->mergeArrays($arr, $parent);
}
private function mergeArrays($ar1, $ar2)
{
foreach ($ar1 as $key => $item) {
if (is_array($item)) {
if (isset($ar2[$key])) {
$ar2[$key] = $this->mergeArrays($item, $ar2[$key]);
} else {
$ar2[$key] = $item;
}
} else {
$ar2[$key] = $item;
}
}
return $ar2;
}
}
$b = new B();
var_dump($b->foo());
输出:
array(3){[&#34; a&#34;] =&gt; string(12)&#34; some value 2&#34; [&#34; B&#34;] =&GT;字符串(10)&#34;一些 值&#34; [&#34; C&#34;] =&GT; array(3){[&#34; ca&#34;] =&gt; string(12)&#34; some value 3&#34; [&#34; CB&#34;] =&GT; string(12)&#34; some value 4&#34; [&#34; CC&#34;] =&GT; string(10)&#34; some value&#34; }}