如何创建一个只继承方法而不继承父类属性的子类?



假设我有以下代码:

首先我创建了父级

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
国家:人口国家:语言:


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


大卫在评论中告诉我将属性设置为私有。我这样做了,它工作正常,但是当我创建一个 Country 对象时,它会在子类中打印父类的属性。

这是代码,当父属性为 Public 时,它为我提供了此输出。

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

语言:


英语

它应该打印:

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

语言: 英语

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

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

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

致命错误:未捕获错误:无法访问受保护的属性 国家::$language 在 C:\xampp\htdocs\ejercicios.php:141 堆栈跟踪:#0 {main} 在第 141 行抛出 C:\xampp\htdocs\ejercicios.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>';
}

}

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

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());

希望这有帮助。

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

反射 API,增加了对类进行逆向工程的功能, 接口、函数、方法和扩展。此外, 反射 API 提供了检索函数的文档注释的方法, 类和方法。

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

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>';
}
} 

演示

最新更新