Базовые интерфейсы



== Traversable ==

Абстрактный базовый интерфейс, который не может быть реализован сам по себе.
Вместо этого ВСЕГДА должен реализовываться IteratorAggregate или Iterator.

interface Stream implements Traversable {}

class InMemoryStream implements IteratorAggregate, Stream
{
    public function getIterator() {}
}

$stream = new InMemoryStream();


== Iterator extends Traversable ==

class myIterator implements Iterator {
    private $position = 0;
    private $array = array(
        "firstelement",
        "secondelement",
        "lastelement",
    );

    public function __construct() {
        $this->position = 0;
    }

    public function rewind() {
        var_dump(__METHOD__);
        $this->position = 0;
    }

    public function current() {
        var_dump(__METHOD__);
        return $this->array[$this->position];
    }

    public function key() {
        var_dump(__METHOD__);
        return $this->position;
    }

    public function next() {
        var_dump(__METHOD__);
        ++$this->position;
    }

    public function valid() {
        var_dump(__METHOD__);
        return isset($this->array[$this->position]);
    }
}

$it = new myIterator;

foreach($it as $key => $value) {
    var_dump($key, $value);
    echo "n";
}


== IteratorAggregate extends Traversable ==

class myData implements IteratorAggregate {
    public $property1 = "Первое свойство";
    public $property2 = "Второе свойство";
    public $property3 = "Третье свойство";

    public function __construct() {
        $this->property4 = "последнее свойство";
    }

    public function getIterator() {
        return new ArrayIterator($this);
    }
}

$obj = new myData;

foreach($obj as $key => $value) {
    var_dump($key, $value);
    echo "n";
}

== Throwable ==

try {
    // Code that may throw an Exception or Error.

} catch (Throwable $t) {
    // Executed only in PHP 7, will not match in PHP 5.x

} catch (Exception $e) {
    // Executed only in PHP 5.x, will not be reached in PHP 7
}

interface MyPackageThrowable extends Throwable {}

class MyPackageException extends Exception implements MyPackageThrowable {}

throw new MyPackageException();

== ArrayAccess ==

class Obj implements ArrayAccess {
    private $container = array();

    public function __construct() {
        $this->container = array(
            "one"   => 1,
            "two"   => 2,
            "three" => 3,
        );
    }

    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }

    public function offsetExists($offset) {
        return isset($this->container[$offset]);
    }

    public function offsetUnset($offset) {
        unset($this->container[$offset]);
    }

    public function offsetGet($offset) {
        return isset($this->container[$offset]) ? $this->container[$offset] : null;
    }
}

$obj = new Obj;

var_dump(isset($obj["two"]));
var_dump($obj["two"]);
unset($obj["two"]);
var_dump(isset($obj["two"]));

$obj["two"] = "A value";
var_dump($obj["two"]);

$obj[] = 'Append 1';
$obj[] = 'Append 2';
$obj[] = 'Append 3';
print_r($obj);


== Serializable ==

class obj implements Serializable {
    private $data;
    public function __construct() {
        $this->data = "Мои закрытые данные";
    }
    public function serialize() {
        return serialize($this->data);
    }
    public function unserialize($data) {
        $this->data = unserialize($data);
    }
    public function getData() {
        return $this->data;
    }
}

$obj = new obj;
$ser = serialize($obj);

var_dump($ser);

$newobj = unserialize($ser);


== Closure ==

function createGreeter($who) {
   return function() use ($who) {
      echo "Hello $who";
   };
}

$greeter = createGreeter("World");
$greeter(); // Hello World

== Generator ==

Объекты Generator не могут быть созданы с помощью оператора new.

function fib($n)
{
    $cur = 1;
    $prev = 0;
    for ($i = 0; $i < $n; $i++) {
        yield $cur;

        $temp = $cur;
        $cur = $prev + $cur;
        $prev = $temp;
    }
}

$fibs = fib(9);
foreach ($fibs as $fib) {
    echo " " . $fib;
}


== WeakReference ==

obj = new stdClass;
$weakref = WeakReference::create($obj);
var_dump($weakref->get());
unset($obj);
var_dump($weakref->get()); // = NULL!

== Stringable ==

class IPv4Address implements Stringable {
    private string $oct1;
    private string $oct2;
    private string $oct3;
    private string $oct4;

    public function __construct(string $oct1, string $oct2, string $oct3, string $oct4) {
        $this->oct1 = $oct1;
        $this->oct2 = $oct2;
        $this->oct3 = $oct3;
        $this->oct4 = $oct4;
    }

    public function __toString(): string {
        return "$oct1.$oct2.$oct3.$oct4";
    }
}

function showStuff(string|Stringable $value) {
    // A Stringable will get converted to a string here by calling __toString.
    print $value;
}

$ip = new IPv4Address('123', '234', '42', '9');

showStuff($ip);