【问题标题】:Referencing an extended class from inside the base class in PHP从 PHP 中的基类内部引用扩展类
【发布时间】:2016-05-26 15:55:38
【问题描述】:

抱歉,可能不是最准确的标题。我很难弄清楚这甚至会被称为什么。

我对 php 的 OOP 有点陌生,因为我的大部分时间都花在了过程编程上。为了更好地学习这些概念,我正在使用一个现有的应用程序并使用 OOP 重写它的一部分。下面的例子是我如何设置基类,然后我将基类扩展成几个更小的类以便于维护。下面,您可以看到我如何扩展基类以创建用户类。 请注意,我的类定义在单独的文件中,但我有一个自动注册它们的工作自动加载器

class EventScheduler{
    function __construct(){
       // set up database connections here
    } 
}

class User extends EventScheduler{
    private function getUserProfile($username){
       // return an array here representing
       // details of passed username from database
    }

    public function getUserType($username){
        return $this->getUserProfile($username)['user_type'];
    }
}

我希望喜欢能够从基类内部引用 User 类,如下所示:

$eventApp = new EventScheduler();
$userType = $eventApp->User->getUserProfile("nameHere");

我目前正在做的是:

$eventApp = new EventScheduler();
 //do some stuff here using the base class

$users = new User();
$userType = $users->getUserProfile("nameHere");

但是当我添加更多子类时,我不想像在那里那样实例化每个扩展类,我希望将它们全部分组在基础对象下,而不是将每个扩展类都包含在其中自己的对象。

【问题讨论】:

  • 我想我不明白你想做什么。 “我想做的是从基类内部引用 User 类”——这违背了扩展类的目的。如果需要子类的方法在基类中,把方法放到基类中。
  • 试图理解你在做什么......在正确的面向对象设计中,父类没有扩展(子)类的概念。如果您希望父类具有子类的某些功能,您可以在父类中定义一个抽象方法,该方法需要所有子类实现。
  • 如果我将额外的用户函数放在我的基类中,我将拥有一个没有良好逻辑分离的庞大基类。无论如何将逻辑分成基类中的不同部分。 Id 基本上想将事物分为用户、房间、建筑物、设备和事件。
  • Users 和 Rooms 应该以什么方式从同一个类扩展?为什么房间和建筑物会从同一个类延伸?房间包含在建筑物中。这显然是一个“你做错了”的案例。
  • 我相信你是对的。顶部有一个权限层,仅允许某些用户修改或保留某些建筑物中的房间。取消类并使用纯函数调用会简单得多;将相似的函数分离到各自的包含文件中。

标签: php class oop


【解决方案1】:

你想做的是

$users = new User();

//do some stuff here using the base class
// ie $users->someFunctionFromEventScheduler();

$userType = $users->getUserProfile("nameHere");

【讨论】:

  • 这个例子与@kainaw 的评论搭配起来非常有意义。它完成了我试图做的事情,但是,以这种方式看到它告诉我它不是解决基类的正确方法,并且以后可能会变得非常混乱。
【解决方案2】:

这是开始阅读 OOP 中常见设计模式的一个很好的理由。网上有很多很好的资源,快速的谷歌搜索会产生大量的结果和示例,大部分都托管在 github 上。

我相信您正在寻找的特定模式是中介模式 (Mediator pattern example in PHP)。不是像您在示例中所做的那样扩展一个类,当您想要一个类的实例可以访问许多其他类的实例时,这些实例都可以通过一个基类相互通信,而不是扩展一个类。前提是“一个好朋友胜过许多熟人”。

举个例子:(接口在这里非常有用,因为它们定义了每个类所需的特定特征)

/**
 * Interface Mediator
 */
interface Mediator {
    /**
     * @param string    $key
     * @param Mediated  $mediated
     * @return void
     */
    public function attach($key, Mediated $mediated);

    /**
     * @param $key
     * @return Mediated
     */
    public function getAttached($key);
}

/**
 * Interface Mediated
 */
interface Mediated {
    /**
     * @param Mediator $mediator
     * @return void
     */
    public function setMediator(Mediator $mediator);

    /**
     * @return Mediator
     */
    public function getMediator();
}

现在我们需要一个基中介类,我将使用您的事件调度程序示例。请注意,它实现了Mediator 接口,因此必须实现接口所需的方法。

/**
 * Class EventScheduler
 */
class EventScheduler implements Mediator {

    /**
     * A collection of mediated instances.
     *
     * @var array
     */
    protected $mediated = [];

    /**
     * @param string $key
     * @param Mediated $mediated
     * @return void
     */
    public function attach($key, Mediated $mediated)
    {
        // So upon attaching a mediated instance we can build the two
        // way binding in one place using the key as the identifier.
        // First we set $this on the mediated instance.
        $mediated->setMediator($this);

        // Then we add this instance to our mediated array inside this instance
        $this->mediated[$key] = $mediated;
    }

    /**
     * @param $key
     * @return Mediated
     */
    public function getAttached($key)
    {
        return $this->mediated[$key];
    }
}

现在我们可以设置一个中介实例。这可以附加到调解器。注意它实现了Mediated 接口。

/**
 * Class User
 */
class User implements Mediated {

    /**
     * @var Mediator
     */
    protected $mediator;

    /**
     * @param Mediator $mediator
     * @return void
     */
    public function setMediator(Mediator $mediator)
    {
        $this->mediator = $mediator;
    }

    /**
     * @return Mediator
     */
    public function getMediator()
    {
        return $this->mediator;
    }
}

您可以创建任意数量的中介实例并将它们附加到Mediator 实例。请记住,这不是特定的中介,因为可以附加许多实例,在大多数情况下,最好明确说明可以附加哪些类,而不是允许通过键进行动态注册。

$scheduler = new EventScheduler();
$user = new User();

$scheduler->attach('user', $user);

// Now we know that we can get the mediator from the User class
$user->getMediator();

// We can also get the User from the mediator itself.
$scheduler->getAttached('user');

当您附加更多类时,您会注意到它们中的每一个都可以使用它们的中介来获取其他附加类的实例,这就是一个好朋友的概念的由来。

这只是一个示例,并没有为简洁起见提供全部功能,但应该让您很好地了解为什么使用常见的设计模式会极大地帮助您,并且如果您想养成良好的习惯,这是学习 OOP 的一个很好的起点。

【讨论】:

    猜你喜欢
    • 2011-10-31
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多