public function withAttribute(string $offset, $value) : self
    {
        if ($this->restricted) {
            if (!in_array($offset, array_keys($this->attributes))) {
                $message = sprintf('%s it not an allowed attribute on this object. The only allowed attributes are %s', $offset, implode(',', array_keys($this->attributes)));
                throw new \InvalidArgumentException($message);
            }
        }

        $that = clone($this);
        $that->attributes[$offset] = $value;
        return $that;
    }