PHP 接口有属性吗?

发布于 2024-08-31 06:19:49 字数 26 浏览 2 评论 0原文

PHP 中的接口有属性,还是只有方法?

Do interfaces in PHP have properties, or do they only have methods?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

川水往事 2024-09-07 06:19:49

您可以在 DocBlock 中为接口声明属性。然后,IDE 将提示接口的这些属性(PhpStorm 会这样做),但这不会强制在实现类中实际实现这些字段。例如

/**
 * @property string $password
 * @property string $username
 */
interface IUserDocument
{


}

You can declare properties in DocBlock for the interface. IDE's will then hint those properties for the interface (PhpStorm does) but this will not force the actual implementation of these fields in the implementing class. E. g.

/**
 * @property string $password
 * @property string $username
 */
interface IUserDocument
{


}
丶情人眼里出诗心の 2024-09-07 06:19:49

这取决于你所说的“属性”是什么意思。如果您指的是实际字段,那么不,它们不是。如果您指的是 C# 中的属性,那么是的,它们可以(因为属性访问器无论如何都是访问器方法的严格语法糖)。事件也是如此(当然,在每种情况下,都没有为 get/setadd/指定实现删除 访问器)。

更新:由于 PHP 没有 get/set 访问器意义上的属性,因此您的问题的答案是否定的。接口不能携带自己的数据/状态。

It depends what you mean by "properties". If you mean actual fields, then no, they don't. If you're referring to properties such as those in C#, then yes they can (since the property accessors are strictly syntactic sugar for accessor methods anyway). The same goes for events (though of course, in each case, no implementation is specified for the get/set or add/remove accessors).

Update: Since PHP does not have properties in the sense of get/set accessors, then the answer to your question is no. Interfaces cannot carry their own data/state.

PHP 中的接口只能包含没有方法主体的公共方法签名。它们还可能包含常量。但仅此而已。没有别的了。

请参阅 http://www.php.net/manual/en/language。 oop5.interfaces.php

接口是使用interface关键字定义的,与标准类的方式相同,但没有任何方法定义其内容。 [...] 接口中声明的所有方法都必须是公共的,这是接口的本质。 [...] 接口可能具有常量。接口常量的工作方式与类常量完全相同,只是它们不能被继承它的类/接口覆盖。

Interfaces in PHP may only contain public method signatures without a method body. They may also contain constants. But that's it. Nothing else.

See http://www.php.net/manual/en/language.oop5.interfaces.php

Interfaces are defined using the interface keyword, in the same way as a standard class, but without any of the methods having their contents defined. […] All methods declared in an interface must be public, this is the nature of an interface. […] Its possible for interfaces to have constants. Interface constants works exactly like class constants except they cannot be overridden by a class/interface that inherits it.

难理解 2024-09-07 06:19:49

PHP 接口可以有常量,但不能有属性(实例变量)。如果您不需要修改您的“属性”,则可以使用常量代替。

PHP interfaces can have constants, but not properties (instance variables). If you don't need to modify your "property", you can use a constant instead.

岁月静好 2024-09-07 06:19:49

PHP 8.4 将发布 Property Hooks,它添加了异步访问器,并在接口中支持这些访问器。

具有公共 getter 的接口:

interface Named
{
    // Objects implementing this interface must have a readable
    // $fullName property.  That could be satisfied with a traditional
    // property or a property with a "get" hook.
    public string $fullName { get; }
}

实现接口的类:

class User implements Named
{
    private bool $isModified = false;
 
    public function __construct(private string $first, private string $last) {}
 
    public string $fullName {
        // Override the "read" action with arbitrary logic.
        get => $this->first . " " . $this->last;
 
        // Override the "write" action with arbitrary logic.
        set { 
            [$this->first, $this->last] = explode(' ', $value, 2);
            $this->isModified = true;
        }
    }
}

简单的公共属性也将满足接口:

class SimpleUser implements Named
{
    public function __construct(public readonly string $fullName) {}
}

阅读 完整 RFC 了解更多详细信息。

PHP 8.4 will ship Property Hooks, which adds asynchronous accessors, and support for these in interfaces.

An interface with a public getter:

interface Named
{
    // Objects implementing this interface must have a readable
    // $fullName property.  That could be satisfied with a traditional
    // property or a property with a "get" hook.
    public string $fullName { get; }
}

A class implementing the interface:

class User implements Named
{
    private bool $isModified = false;
 
    public function __construct(private string $first, private string $last) {}
 
    public string $fullName {
        // Override the "read" action with arbitrary logic.
        get => $this->first . " " . $this->last;
 
        // Override the "write" action with arbitrary logic.
        set { 
            [$this->first, $this->last] = explode(' ', $value, 2);
            $this->isModified = true;
        }
    }
}

A simple public property will also satisfy the interface:

class SimpleUser implements Named
{
    public function __construct(public readonly string $fullName) {}
}

Read the full RFC for more details.

好听的两个字的网名 2024-09-07 06:19:49

我迟到了,但这可能会对将来的某人有所帮助......接口不应该有属性,因为它对应于实现(即,对应于类)。这些属性必须用于表示类的内部状态。接口更多的是一种类型,它定义了该类型可以做什么或不能做什么(方法)。

该对象必须具有足够的通用性和解耦性,才能对其类型做出响应。

参考书设计模式 - Erich Gamma

使用接口的方式(>8 的语法)

<?php

interface Transport {
    public function ticketCode();
}

interface Vehicle {
    public function start();
    public function stop();
    public function getStatus();
}

class Cab implements Transport, Vehicle {
    private string $ticket;
    private string $status;
    
    function __construct(){
        $this->ticket = time();
        $this->status = "off";
    }

    public function start(){
        $this->status = 'on';
    }
    
    public function stop(){
        $this->status = 'off';
    }
    
    public function getStatus(){
        echo "The status is: {$this->status}";
    }
    
    public function ticketCode() {
        echo "The ticket code is: {$this->ticket}";
    }
}

class Motorcycle implements Vehicle {
    private string $status;
    
    function __construct(){
        $this->status = "off";
    }

    public function start(){
        $this->status = 'on';
    }
    
    public function stop(){
        $this->status = 'off';
    }
    
    public function getStatus(){
        echo "The status is: {$this->status}";
    }
}

$cab = new Cab();
echo " > cab is a Transport? " . ($cab instanceof Transport ? 'yes':'no') . " || cab is a Vehicle? " .  ($cab instanceof Vehicle ? 'yes':'no'); 

$motorcycle = new Motorcycle();
echo " > motorcycle is a Transport? " . ($motorcycle instanceof Transport ? 'yes':'no') . " || motorcycle is a Vehicle? " . ($motorcycle instanceof Vehicle?'yes':'no'); 

在前面的示例中,我们可以看到接口如何定义我的类将采用的类型(一个类可以有不止一种类型),该类负责定义这些类型的实现和交互方式。因此,这解释了为什么接口不允许拥有属性(不,这不是语言错误),它实际上是应该管理和定义状态(属性)的类。必须操纵它们并改变它们的值的是对象或类实例。接口只是说它必须实现类才被认为是某种类型,接口不能做的事情。

function startVehicle(Vehicle $vehicle){
    $vehicle->start();
}

$motorcycle->getStatus();
$cab->getStatus();
startVehicle($motorcycle);
startVehicle($cab);
$motorcycle->getStatus();
$cab->getStatus();

使用接口将允许您进行诸如多态性或按类型处理对象(类实例或任何您想称呼它的东西)之类的事情,无论它们来自哪个类,只要它实现了“X”类型,它就是一个有效的对象使用其接口执行操作(在上面的示例中,类型为 Vehicle)。

接口确实是一个接口,我将其称为类型,以便更容易理解它的方法。

RESUME

如果您想要一个带有属性的界面,那么您的解决方案设计得很糟糕,需要重新考虑。也许我应该考虑类继承。

考虑到类可以同等地被视为一种类型,或者我提到的一种类型,这种解释可能看起来有争议,但这个概念理解起来有些复杂,我邀请您阅读前面提到的可以更好地解释这种差异的书。那个我。

I'm late but this may help someone in the future... Interfaces should not have properties, since that corresponds to the implementation (ie, to the class). The properties must be used for the representation of the internal state of the class. The interface is more of a type and defines what that type can or cannot do (methods).

The object must be sufficiently versatile and decoupled to give responses to its types.

Reference book: Design Patterns - Erich Gamma

The way to use interfaces (syntax for >8)

<?php

interface Transport {
    public function ticketCode();
}

interface Vehicle {
    public function start();
    public function stop();
    public function getStatus();
}

class Cab implements Transport, Vehicle {
    private string $ticket;
    private string $status;
    
    function __construct(){
        $this->ticket = time();
        $this->status = "off";
    }

    public function start(){
        $this->status = 'on';
    }
    
    public function stop(){
        $this->status = 'off';
    }
    
    public function getStatus(){
        echo "The status is: {$this->status}";
    }
    
    public function ticketCode() {
        echo "The ticket code is: {$this->ticket}";
    }
}

class Motorcycle implements Vehicle {
    private string $status;
    
    function __construct(){
        $this->status = "off";
    }

    public function start(){
        $this->status = 'on';
    }
    
    public function stop(){
        $this->status = 'off';
    }
    
    public function getStatus(){
        echo "The status is: {$this->status}";
    }
}

$cab = new Cab();
echo " > cab is a Transport? " . ($cab instanceof Transport ? 'yes':'no') . " || cab is a Vehicle? " .  ($cab instanceof Vehicle ? 'yes':'no'); 

$motorcycle = new Motorcycle();
echo " > motorcycle is a Transport? " . ($motorcycle instanceof Transport ? 'yes':'no') . " || motorcycle is a Vehicle? " . ($motorcycle instanceof Vehicle?'yes':'no'); 

In the previous example we can see how the interfaces define the types that my class will take (a class can have more than one type), the class is in charge of defining how those types are implemented and interact. So, this explains why an interface doesn't allow having properties (No, it's not a language error), it's really the class that should manage and define the states (properties). Who must manipulate them and change their values is the object or class instance. The interface simply says that it must implement the class to be considered a certain type, an interface must not do things.

function startVehicle(Vehicle $vehicle){
    $vehicle->start();
}

$motorcycle->getStatus();
$cab->getStatus();
startVehicle($motorcycle);
startVehicle($cab);
$motorcycle->getStatus();
$cab->getStatus();

Using interfaces will allow you things like polymorphism or working with objects (class instances or whatever you want to call it) by type regardless of the class they come from, as long as it implements the "X" type it will be a valid object to do things with its interface (in example above, the type would be Vehicle).

The interface is really an interface, I have called it type so that it can be easier to understand the approach it has.

RESUME

If you want an interface with properties then you have badly designed your solution and need to rethink it. Maybe I should be thinking about class inheritance.

The explanation may seem controversial considering that a class can equally be treated as a type, or what I mention as a type, but the concept is somewhat more complex to understand and I invite you to read the aforementioned book that can explain the difference better. that I.

你是年少的欢喜 2024-09-07 06:19:49

在接口中需要属性的[有效]原因是指定 DTO 类具有某个方面,例如 IOrderable { OrderDate, OrderStatus }、IDeliverable { DeliveryAddress, Route, ... } 等。该方面可以用于许多 DTO,例如销售订单、工作订单、销售发票等。DTO 类可以支持多个方面,即多重继承,这在数据类(但不是代码类)中是理想的。此后,DTO 的客户端确信可以通过该方面(接口合约)查看 DTO。该模式遵守所有 5 条 SOLID 原则。

在 PHP 中,最接近接口属性的是 Traits http://php.net /manual/en/language.oop5.traits.php。与接口类似,特征无法实例化,但可以直接在类中使用而无需实现它们。

The [valid] reason for needing properties in an interface is to specify that a DTO class has a certain aspect, e.g. IOrderable { OrderDate, OrderStatus }, IDeliverable { DeliveryAddress, Route, ... }, etc. The aspect can be used in a number of DTOs e.g. Sales Order, Work Order, Sales Invoices, etc. A DTO class can support multiple aspects, i.e. multiple inheritance which is desirable in Data Classes (but not Code Classes). Thereafter, the client of the DTO is assured it can view the DTO through that aspect (an interface contract). This pattern abides by all 5 of the SOLID principles.

In PHP the closest you have to interface properties is traits http://php.net/manual/en/language.oop5.traits.php. Similar to interfaces, traits cannot be instantiated, however can be used directly in classes without implementing them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文