We help IT Professionals succeed at work.

What would this interface look like?

Bruce Gust
Bruce Gust asked
on
I've been asked to create a class that "implements this interface."

Not sure what that means or what that would look like.

What do you think?

<?php

namespace App\Data;

/**
 * An immutable collection of values with operators for manipulation or check.
 */
interface RangeFinderInterface extends \IteratorAggregate
{
    public function __construct(iterable $values = []);

    /**
     * Returns values that are between, and including, the passed values. [min, max]
     *
     * For the purpose of this code challenge, all non-numeric values should be dropped.
     *
     * @param int|float|string $min
     * @param int|float|string $max
     *
     * @return static
     */
    public function between($min, $max): self;

    public function after($min): self;

    public function before($max): self;

    /**
     * @param callable|null $by Accepts a single argument and returns a boolean `fn(mixed): bool`
     *
     * @return static
     */
    public function filter(?callable $by): self;

    /**
     * @param callable $by Accepts a single argument and returns a boolean `fn(mixed): bool`
     *
     * @return bool
     */
    public function some(callable $by): bool;

    /**
     * @param callable $by Accepts a single argument and returns a boolean `fn(mixed): bool`
     *
     * @return bool
     */
    public function every(callable $by): bool;

    /**
     * @return array
     */
    public function all(): array;
}

Open in new window

Comment
Watch Question

CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
Commented:
Hey Bruce,

In Object Oriented Programming, an Interface is something along the lines of a contract. Any class that implements an Interface, MUST implement all members of that interface.

To do this in PHP, you add implements InterfaceName to the class. You then need to write the code to create the concrete implementation of the Interface members (the code that actually does something), so something like this:

class MyClass implements RangeFinderInterface 
{
    private $values;

    public function __construct(iterable $values = []) 
    {
        $this->values = $values;
    }

    public function between($min, $max): self
    {
        // write the code to run when this method is called
    }

    public function after($min): self
    {
        // write the code to run when this method is called
    }

    ...
}

Open in new window

Basically, there are a few reasons why we use Interfaces (a quick google will give you plenty of info), but it means that we can have different implementations of the same interface. By definitions, they will all have exactly the same methods - just different code behind them. We can then code against the Interface, rather than a concrete implementation and this allows flexibility, testability and scalabilty
Bruce GustPHP Developer

Author

Commented:
You know what I hate, Chris...?

Code Evaluations.

Any time I get interviewed for a gig, there's a part of me that just cringes at the thought of a "code challenge" because it inevitably means that I'm going to be quizzed on something I've never used. I'm going to bust my tail in an effort to get it done, I'm going to feel inept and ridiculous in the process and all of this knowing that there's a good chance that whatever good impression I've made up to this point is going to be like a balloon where all the air has suddenly been let out.

I've never used interfaces or abstract classes for that matter. There was Symfony syntax at the top of the page and I originally submitted a weak looking Symfony page, having know idea what I was doing.

They gave you a four hour window to make any changes and it was then that I realized it was a PHP dynamic. This is what I finally submitted:

<?php

class Evaluation implements RangeFinderInterface {
      public function between();
      public function after();
      public function before();
      public function filter();
      public function some();
      public function every();
      public function all();
      
      $this-> between();
      $this-> after();
      $this-> before();
      $this-> filter();
      $this-> some();
      $this-> every();
      $this-> all();
}

class Measurement {
      public function lookup(RangeFinderInterface $method) {
            $method->all();
      }
}

$newEval = new Evaluation();
$hit_me = new Measurement();
$hit_me->lookup($newEval);

?>

Not sure if that's even close. The file size limit was 2 MB and they asked for a zip file...

The above is 2 KB.

Man...
Bruce GustPHP Developer

Author

Commented:
Thanks, bud!
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019

Commented:
No worries Bruce,

I've never seen the point of putting interviewees on the spot like that - it never actually reflects real life. Every developer I know will always have their IDE of choice open and a hundred different browser tabs with Google search results (and of course a good helping of Experts Exchange pages !)

What you've done isn't really how you implement an interface, but I guess it's too late now :)

Once you've implemented the class as above, then you just instantiate it like any other. Because your methods are returning 'self', you can chain your methods:

class Evaluation implements RangeFinderInterface 
{
    private $values;

    // create your concrete Interface implementations here
    public function __construct(iterable $values = []) 
    {
        $this->values = $values;
    }

    public function between($min, $max): RangeFinderInterface
    {
        $this->values = //filter your values here
        return new self($this->values);
    }

    ...
}

Open in new window


and then

$eval = new Evaluation($someValues);
$all = $eval->between(5, 12)->after(7)->all();
var_dump($all)

Open in new window