Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

idea: add AbstractCollection #268

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions docs/pages/code/extending-collection-with-abstract-class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<?php

declare(strict_types=1);

include __DIR__ . '/../../../vendor/autoload.php';

use Generator;
use loophp\collection\AbstractCollection;
use loophp\collection\Contract\Collection as CollectionInterface;
use loophp\collection\Operation\Range;
use loophp\collection\Operation\Times;
use loophp\collection\Operation\Unfold;
use loophp\iterators\ClosureIteratorAggregate;
use loophp\iterators\IterableIteratorAggregate;
use loophp\iterators\ResourceIteratorAggregate;
use loophp\iterators\StringIteratorAggregate;
use NoRewindIterator;
use Traversable;

use const INF;

final class MyCustomFoobarCollection extends AbstractCollection
{
/**
* @var ClosureIteratorAggregate<TKey, T>
*/
private ClosureIteratorAggregate $innerIterator;

/**
* @param callable(mixed ...$parameters): iterable<TKey, T> $callable
* @param iterable<int, mixed> $parameters
*/
private function __construct(callable $callable, iterable $parameters = [])
{
$this->innerIterator = new ClosureIteratorAggregate($callable, $parameters);
}

/**
* @template UKey
* @template U
*
* @return self<UKey, U>
*/
public static function empty(): CollectionInterface
{
return new self(static fn (): Generator => yield from []);
}

/**
* @template UKey
* @template U
*
* @param callable(mixed ...$parameters): iterable<UKey, U> $callable
* @param iterable<int, mixed> $parameters
*
* @return self<UKey, U>
*/
public static function fromCallable(callable $callable, iterable $parameters = []): self
{
return new self($callable, $parameters);
}

/**
* @return self<int, string>
*/
public static function fromFile(string $filepath): self
{
return new self(
static fn (): Generator => yield from new ResourceIteratorAggregate(fopen($filepath, 'rb'), true),
);
}

/**
* @template UKey
* @template U
*
* @return self<UKey, U>
*/
public static function fromGenerator(Generator $generator): self
{
return new self(static fn (): Generator => yield from new NoRewindIterator($generator));
}

/**
* @template UKey
* @template U
*
* @param iterable<UKey, U> $iterable
*
* @return self<UKey, U>
*/
public static function fromIterable(iterable $iterable): self
{
return new self(static fn (): Generator => yield from new IterableIteratorAggregate($iterable));
}

/**
* @param resource $resource
*
* @return self<int, string>
*/
public static function fromResource($resource): self
{
return new self(static fn (): Generator => yield from new ResourceIteratorAggregate($resource));
}

/**
* @return self<int, string>
*/
public static function fromString(string $string, string $delimiter = ''): self
{
return new self(static fn (): Generator => yield from new StringIteratorAggregate($string, $delimiter));
}

/**
* @return Traversable<TKey, T>
*/
public function getIterator(): Traversable
{
yield from $this->innerIterator->getIterator();
}

public static function range(float $start = 0.0, float $end = INF, float $step = 1.0): CollectionInterface
{
return new self((new Range())()($start)($end)($step));
}

public static function times(int $number = 0, ?callable $callback = null): CollectionInterface
{
return new self((new Times())()($number)($callback));
}

public static function unfold(callable $callback, ...$parameters): CollectionInterface
{
return new self((new Unfold())()(...$parameters)($callback));
}
}
16 changes: 13 additions & 3 deletions docs/pages/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,12 @@ enough.
Then, you would like to create your own collection class with some specific
feature added on top of it.

Every classes of this library are ``final`` and then it is impossible to use
inheritance and use the original Collection class as parent of another one.
The main Collection class of this library is ``final`` and then it is impossible
to use inheritance and use the original Collection class as parent of another
one.

If you want to **extend** the Collection, you must use the Composition pattern.
If you want to **extend** the Collection, you have to use the Composition
pattern or extend the new AbstractCollection class available since version 7.

You can read more about Inheritance and Composition by doing a query on your
favorite search engine. I also wrote an `article`_ about this.
Expand All @@ -114,6 +116,14 @@ new Operation ``foobar``.
.. literalinclude:: code/extending-collection.php
:language: php

Since version 7, you can extend the provided abstract class which implements
most of the available methods. The only methods that are left to implements are
the static constructors, you can simply copy paste them from the main Collection
class.

.. literalinclude:: code/extending-collection-with-abstract-class.php
:language: php

Manipulate strings
~~~~~~~~~~~~~~~~~~

Expand Down
Loading