1<?php
2
3/**
4 * This file is part of the ramsey/collection library
5 *
6 * For the full copyright and license information, please view the LICENSE
7 * file that was distributed with this source code.
8 *
9 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
10 * @license http://opensource.org/licenses/MIT MIT
11 */
12
13declare(strict_types=1);
14
15namespace Ramsey\Collection\Map;
16
17use Ramsey\Collection\Tool\TypeTrait;
18
19/**
20 * A `TypedMap` represents a map of elements where key and value are typed.
21 *
22 * Each element is identified by a key with defined type and a value of defined
23 * type. The keys of the map must be unique. The values on the map can be=
24 * repeated but each with its own different key.
25 *
26 * The most common case is to use a string type key, but it's not limited to
27 * this type of keys.
28 *
29 * This is a direct implementation of `TypedMapInterface`, provided for the sake
30 * of convenience.
31 *
32 * Example usage:
33 *
34 * ```php
35 * $map = new TypedMap('string', Foo::class);
36 * $map['x'] = new Foo();
37 * foreach ($map as $key => $value) {
38 *     // do something with $key, it will be a Foo::class
39 * }
40 *
41 * // this will throw an exception since key must be string
42 * $map[10] = new Foo();
43 *
44 * // this will throw an exception since value must be a Foo
45 * $map['bar'] = 'bar';
46 *
47 * // initialize map with contents
48 * $map = new TypedMap('string', Foo::class, [
49 *     new Foo(), new Foo(), new Foo()
50 * ]);
51 * ```
52 *
53 * It is preferable to subclass `AbstractTypedMap` to create your own typed map
54 * implementation:
55 *
56 * ```php
57 * class FooTypedMap extends AbstractTypedMap
58 * {
59 *     public function getKeyType()
60 *     {
61 *         return 'int';
62 *     }
63 *
64 *     public function getValueType()
65 *     {
66 *          return Foo::class;
67 *     }
68 * }
69 * ```
70 *
71 * … but you also may use the `TypedMap` class:
72 *
73 * ```php
74 * class FooTypedMap extends TypedMap
75 * {
76 *     public function __constructor(array $data = [])
77 *     {
78 *         parent::__construct('int', Foo::class, $data);
79 *     }
80 * }
81 * ```
82 *
83 * @phpstan-ignore-next-line
84 * @template K as array-key
85 * @template T
86 * @template-extends AbstractTypedMap<K, T>
87 */
88class TypedMap extends AbstractTypedMap
89{
90    use TypeTrait;
91
92    /**
93     * The data type of keys stored in this collection.
94     *
95     * A map key's type is immutable once it is set. For this reason, this
96     * property is set private.
97     *
98     * @var string data type of the map key.
99     */
100    private $keyType;
101
102    /**
103     * The data type of values stored in this collection.
104     *
105     * A map value's type is immutable once it is set. For this reason, this
106     * property is set private.
107     *
108     * @var string data type of the map value.
109     */
110    private $valueType;
111
112    /**
113     * Constructs a map object of the specified key and value types,
114     * optionally with the specified data.
115     *
116     * @param string $keyType The data type of the map's keys.
117     * @param string $valueType The data type of the map's values.
118     * @param array<K, T> $data The initial data to set for this map.
119     */
120    public function __construct(string $keyType, string $valueType, array $data = [])
121    {
122        $this->keyType = $keyType;
123        $this->valueType = $valueType;
124        parent::__construct($data);
125    }
126
127    public function getKeyType(): string
128    {
129        return $this->keyType;
130    }
131
132    public function getValueType(): string
133    {
134        return $this->valueType;
135    }
136}
137