【问题标题】:How can I create a child class which only inherits the methods but not the properties of the parent?如何创建一个只继承方法但不继承父属性的子类?
【发布时间】:2019-11-27 20:51:17
【问题描述】:

假设我有这个代码:

首先我创建了父级

 class Country {
  public $country;
  public $populationcountry;
  public $language;     

使用一些方法(与这个问题无关)

public function function1() {   }
public function function2() {    }
             .
             .
                }  //end of parent class

然后我创建孩子

 Class city extends Country 
{
public $populationcity;
} 

然后我创建对象(在这个例子中我只创建了一个)

$city1 = new city();

$city1->populationcity = 10000; 

还有一个对象数组

$cities = [$city1];    

最后我只想“回显”孩子的属性(人口城市)

foreach ($cities as $city) {
foreach ($city as $k => $v) {
$city->populationcity;
echo $k . ': ' . $v . '<br>';
 }
}   

输出
人口城市:10000
国家:
人口国家:
语言:

我想保留父级的方法,而不是父级的属性。我怎样才能做到这一点?


cmets 中的 David 告诉我将属性设置为 Private。我这样做了,它工作得很好,但是当我创建一个 Country 对象时,它会在子类中打印父级的属性。

这是代码,它在父属性为 Public 时给我这个输出。

人口城市:10000
国家:
人口国家:
语言:
国家:英格兰
人口国家:30000
语言:英语

应该打印出来:

人口城市:10000
国家:英格兰
人口国家:30000
语言:英语

当我将它们设置为私有时,我得到了这个:

致命错误:未捕获的错误:无法访问 C:\xampp\htdocs\ejercicios.php:141 中的私有属性 Country::$language 堆栈跟踪:C:\xampp\htdocs\ejercicios 中抛出 #0 {main}。第 141 行的 php

当我将它们设置为受保护时,我得到了这个:

致命错误:未捕获错误:无法访问 C:\xampp\htdocs\ejercicios.php:141 中的受保护属性 Country::$language 堆栈跟踪:C:\xampp\htdocs\ejercicios 中抛出 #0 {main}。第141行的php

class Country {
  public $country;
  public $populationcountry;
  public $language;
  }

Class city extends Country 
{
public $populationcity;
}

$country1 = new Country();
$country1->language = 'English';
$country1->country = 'ENgland';
$country1->populationcountry = 30000;
$countries = [$country1];

$city1 = new city();
$city1->populationcity = 10000;

$cities = [$city1];

foreach ($cities as $city) {
 foreach ($city as $k => $v) {
$city->populationcity;
echo $k . ': ' . $v . '<br>';
}
}

foreach ($countries as $country) {
foreach ($country as $k => $v) {
$country->language;
$country->populationcountry;
$country->country; 
echo $k . ': ' . $v . '<br>';

}

}

【问题讨论】:

  • 只需将属性设为私有即可。
  • 嘿大卫。谢谢!它适用于这个例子。但是,我添加了一个小的复杂性,它没有按预期工作。我在哪里可以给你看代码?这个评论太长了。我应该编辑帖子还是发布答案?谢谢
  • 是的,只需编辑您的问题。
  • 我刚刚做到了!谢谢!

标签: php inheritance properties parent-child


【解决方案1】:

您可以使用Reflection 来实现此目的。

反射 API 增加了逆向工程类的能力, 接口、函数、方法和扩展。此外, 反射 API 提供了检索函数的 doc cmets 的方法, 类和方法。

这将允许您枚举属性并查看是否在类本身或沿其继承链中定义了任何给定的属性。

foreach ($cities as $city) {
    /* You can move this logic out of the loop and cache the properties 
       if your array contains only elements of the same type */
    $reflector = new ReflectionClass($city);
    $class = $reflector->getName(); // Get the name of the current class

    $ownProperties = array_map(function ($e) { return $e->name; },  // Return only the name of 
    // the property
        array_filter($reflector->getProperties(), // Return properties defined in 
        // the same class only, regardless the visibility, since protected properties can
        // either be declared or inherited
             // Check if declaring class is the same as this type
            function($e) use ($class) { return $class === $e->class; } ));
      /* **** */
    foreach ($ownProperties as $property) {
        echo $property . ': ' . $city->$property . '<br>';
    }
} 

Demo

【讨论】:

    【解决方案2】:

    看起来像一个糟糕的设计模式。对我来说,一个国家可以包含几个不同的城市。因此,城市不是国家。你的国家实体类不应该是这样的吗?

    class Country
    {
        /**
         * Collection of City objects
         * @var ArrayObject
         */
        protected $cities;
        protected $name;
        protected $population;
        protected $language;
    
        public function setCity(City $city) : self
        {
            if ($this->cities == null) {
                $this->cities = new ArrayObject();
            }
    
            $this->cities->append($city);
            return $this;
        }
    
        public function getCities() : ArrayObject
        {
            if ($this->cities == null) {
                $this->cities = new ArrayObject();
            }
    
            return $this->cities;
        }
    }
    

    无论如何...让我们用 php 自己的反射类解决您的问题。要获取声明类的属性,只需在 city 类中实现以下函数即可。

    class City extends Country
    {
        public $populationCity;
    
        public function getData() : array
        {
            $data = [];
            $reflection = new ReflectionClass($this);
            $properties = $reflection->getProperties(ReflectionProperty::IS_PUBLIC);
    
            foreach ($properties as $property) {
                if ($property->getDeclaringClass() == $reflection) {
                    $data[$property->getName()] = $property->getValue($this);
                }
            }
    
            return $data;
        }
    }
    

    有了这个,您只能获取City 类的属性。让我们试一试...

    $city = new City();
    $city->populationCity = 10000;
    
    var_dump($city->getData());
    

    希望这会有所帮助。

    【讨论】:

    • 谢谢马塞尔!我可能需要一些时间来掌握反射功能。我编辑了我的问题并添加了更多细节。希望有更简单的方法来解决它。 (是的,这是一个糟糕的设计,我只是用它作为一个例子,我没有多想,只是想构建一个我只需要继承方法而不是属性的例子)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    • 1970-01-01
    • 2012-05-03
    • 1970-01-01
    • 1970-01-01
    • 2015-05-08
    • 2020-11-08
    相关资源
    最近更新 更多