doumouyi4039 2018-05-11 13:29
浏览 59
已采纳

具有许多属性的不可变对象

I've got a class that I want to make immutable but that class has a lot of properties.

<?php

class Gameworld {

    /** @var string */
    private $name;

    /** @var string */
    private $type;

    /** @var bool */
    private $is_online;

    /** @var int */
    private $online_players;

    /** @var int */
    private $online_players_record;

    /** @var string */
    private $description;

    /** @var string */
    private $location;

    /** @var \DateTime */
    private $created_at;

}

How to create such object? When I introduce public function __construct() with all those properties it will get bloated. If I introduce setters it won't be immutable anymore.


EDIT: I was thinking about making setters but ones that could be only used once. Thanks to that I won't have bloated constructor but for some reason it seems not like a good idea. Something like:

class Gameworld {

    ... old properties ...

    /** @var array */
    private $used_setters = [];

    public function setName(string $name){
        if(in_array('name', $this->used_setters)){
            throw new ImmutableException('Class Gameworld is immutable.');
        }

        $this->name = $name;
        $this->used_setters[] = 'name';
    }

}
  • 写回答

2条回答 默认 最新

  • douci1677 2018-05-11 14:29
    关注

    I would use __set() magic method to check if the value is set else I would throw an exception:

    class Gameworld {
    
        /** @var string */
        private $name;
    
        /** @var string */
        private $type;
    
        /** @var bool */
        private $is_online;
    
        /** @var int */
        private $online_players;
    
        /** @var int */
        private $online_players_record;
    
        /** @var string */
        private $description;
    
        /** @var string */
        private $location;
    
        /** @var \DateTime */
        private $created_at;
    
        public function __set($property, $value)  
        {  
            if (property_exists($this, $property)) {  
                if(is_null($this->$property)){
                    $this->$property = $value;
                    return $this;
                }
                throw MyCustomException();
            }
            throw UndefinedClassVariableException();
        }
    }
    

    A basic usage would be:

    $x = new Gameworld();
    $x->name = "OK";
    $x->is_online = true;
    $x->name="Exception";
    

    P.S: Exceptions must extend the base exception class or you could trigger or log an error, depends on what you want

    P.S.S: An alternative sollution would be to use __call() method and check if the value is null

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用
  • ¥15 C++ yoloV5改写遇到的问题
  • ¥20 win11修改中文用户名路径
  • ¥15 win2012磁盘空间不足,c盘正常,d盘无法写入
  • ¥15 用土力学知识进行土坡稳定性分析与挡土墙设计
  • ¥70 PlayWright在Java上连接CDP关联本地Chrome启动失败,貌似是Windows端口转发问题
  • ¥15 帮我写一个c++工程