从课外

时间:2018-01-22 06:45:50

标签: php protected solid-principles

PHP 7中有哪些策略用于从第二类A类中的方法修改一个类B类的受保护属性,即使这些类不相关?

在实现嵌套类的语言中,这根本不是问题。 B类可以(并且应该)嵌套在A类中。然后,B类可以是受保护的类,属性可以是公共的。

创意#1

如果B类是A类的孩子,这非常容易。但是,这两个类是无关的。因此,这甚至不是一种选择。

创意#2

我考虑在B类中使用公共方法来更改属性的值,这可以由A类调用。不幸的是,这允许任何人更改属性的值,而不是只是A级。

创意#3

我的下一个想法是获取一个指向受保护变量的指针,从A类中设置它,然后取消设置它。像这样:

<?php

class A {

    protected $b;

    public function __construct() {

        $this->b = new B( $pointer );

        // do processing that requires B to be instantiated but has
        // not yet determined an appropriate value for the property

        $pointer = 12;
        unset( $pointer );

    }

}

class B {

    protected $value;

    public function __construct( &$pointer ) {

        $this->value =& $pointer;

    }

}

var_dump( new A );

?>

这会使A级和B级紧密耦合吗?根据我的理解,它会,而且我想避免这种情况。我希望我的理解是错误的,这是一个可以接受的解决方案。

PHP 7中是否有其他可以在不破坏SOLID设计原则的情况下实现此目标的变通方法?

提前感谢大家的时间!

既然已经提出要求,这就是我要解决的实际问题。我有一个名为Client的类和一个名为Receipt的类。可以请求Client对象向服务器发送消息,它将返回一个Receipt对象。这是异步发生的,所以稍后在脚本中我可以使用Receipt对象来获取响应(使用getResponse()方法)。我还希望收据具有getTime()方法,以便您可以检查请求/响应周期完成的时间。这是我正在努力完成的一个淡化版本:

<?php

class Client {

    protected $receipts = [];

    public function sendRequest( $destination, $request ) {

        // put response in database and get the inserted row ID

        $this->receipts[] = [

            'timeStart' => microtime( true ),
            'receipt' => ($receipt = new Receipt( $rowID ))

        ];

        return $receipt;

    }

    public function setSignal( $signal ) {

        pcntl_signal( $signal, function() {

            // while there is a new response in the database

                // get the $receipt from $this->receipts that matches the response

                $receipt->receipt->time = microtime( true ) - $receipt->timeStart;

                unset( $this->receipts[$index] );
                break;

            // end while

        } );

    }

}

class Receipt {

    protected $rowID, $time;

    public function __construct( $rowId ) {

        $this->rowID = $rowID;

    }

    public function getTime() {

        return $this->time;

    }

}

$client = new Client;
$client->setSignal( SIGIO );

$receipt = $client->sendRequest( 'some destination', 'my request' );

echo $receipt->getTime(); // NULL
sleep( 1 );
echo $receipt->getTime(); // NULL
sleep( 1 );
echo $receipt->getTime(); // NULL
sleep( 1 );
echo $receipt->getTime(); // NULL
sleep( 1 );
echo $receipt->getTime(); // 4.2

?>

所以问题就在于:

$ receipt-&gt;收据 - &gt; time = microtime(true) - $ receipt-&gt; timeStart;

因为“time”是Receipt对象的受保护属性。

1 个答案:

答案 0 :(得分:0)

好的,我认为我已经提出了最好的解决方案,我可以提出原始问题(从另一个类更新受保护的变量)。我不确定这是如何与SOLID原则叠加的,但我认为它会相当不错。

在我看来,最好的解决方案是创建一个公共方法,允许对象从数据库中的行刷新本身,而不是公开方法来专门更新值取出后。像这样:

<?php

class A {

    protected $database, $b;

    public function __construct() {

        $this->b = new B;

        // do HALF of the processing that requires B to be instantiated
        // but has not yet determined an appropriate value for the property

        $this->b->refresh();

    }

}

class B {

    protected $database, $value;

    public function refresh() {

        // do the other half of the things

        $this->value = 12;

    }

}

var_dump( new A );

?>

对我原帖的评论指出我在问XY问题。在阅读完文章之后,它完全合情合理,我理解我的问题可能因为我的问题而难以回答。感谢所有尝试的人,无论如何!对于遇到类似问题的人,我会留在这里。