> Indeed, the current implementation appears to have several problems. So, > how about the following implementation? > > ```php > interface RandomNumberGenerator > { > public function generate(): int; > } > > final class Random > { > private RandomNumberGenerator $rng; > public function __construct(?RandomNumberGenerator $rng = null) > { > $this->rng = $rng ?? new XorShift128Plus(random_int(PHP_INT_MIN, > PHP_INT_MAX)); > } > public function nextInt(): int {} > public function getInt(int $min, int $max): int {} > public function getBytes(int $length): string {} > public function shuffleArray(array $array): array {} > public function shuffleString(string $string): string {} > public function __serialize(): array {} > public function __unserialize(array $data): void {} > } > > class XorShift128PlusNumberGenerator implements RandomNumberGenerator > { > public function generate(): int {} > public function __serialize(): array {} > public function __unserialize(array $data): void {} > } > > class MT19937NumberGenerator implements RandomNumberGenerator > { > public function generate(): int {} > public function __serialize(): array {} > public function __unserialize(array $data): void {} > } > > class SecureNumberGenerator implements RandomNumberGenerator > { > public function generate(): int {} > } > ``` > > This is an approach similar to Nikita's `createDefault`. If the > constructor has a null argument, it uses the default, XorShift128+, > internally. > > Also, whether the Random class is serializable or clonable depends on the > instance of RandomNumberGenerator being used. This means that when the > Random class clone is called, the `$rng` member will be implicitly cloned. > > How about this? >
Hello, thanks for thinking again. A few editorial notes: - I guess that would be "new XorShift128PlusNumberGenerator" (like the class name)? - The non-Secure implementations' stubs are probably missing `public function __construct(?int $seed = null) {}`? - The Random class' and non-Secure implementations' stubs are probably missing `public function __clone(): void {}` (like `__serialize()`)? That would let us use the API like this: 1. Construction: one of: - default RNG and seed: `$random = new Random();` - chosen RNG, default seed: e.g. `$random = new Random(new MT19937NumberGenerator());` - chosen RNG and seed: e.g. `$random = new Random(new MT19937NumberGenerator(1234));` (no "default RNG, chosen seed", but the default RNG can be documented, and one could argue that a chosen seed only makes sense with a chosen RNG anyway) 2. Usage: `$int = $random->nextInt();`, `$percent = $random->getInt(0, 100);`, `$dword = $random->getBytes(4);`, `$shuffledList = $random->shuffleArray($list);` etc. I think this is well-consistent with the "pure design" described by Nikita, and I personally find it both flexible/extensible and easy-to-use =) (Just beware that the namespace question will probably pop up again.) PS: I feel like my numerous questions/suggestions (in this thread and the previous ones) may also have caused some deviations, so I hope that I won't need more and that other participants will reach a consensus... Best regards, -- Guilliam Xavier