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

It would be nice to be able to inherit the Ok and Err Result classes #16

Closed
MattyRad opened this issue Jul 10, 2023 · 4 comments
Closed

Comments

@MattyRad
Copy link
Contributor

MattyRad commented Jul 10, 2023

I currently have a client that returns my own (very similar) Result object:

public function resolve(MyOwnNamespace\Client\Request $request): MyOwnNamespace\Client\Result

Ok/Err are marked final, which makes sense. However, being able to extend them would drastically reduce the diffs and footprint of this library as a dependency. For example,

namespace MyOwnNamespace\Client\Result;

class Err extends \TH\Maybe\Result\Err implements \MyOwnNamespace\Client\Result

This would import all the functionality of \TH\Maybe\Result\Err, and prevent the need to change function signatures all throughout the app. Thoughts on making this change?

@mathroc
Copy link
Member

mathroc commented Jul 10, 2023

I wondered about allowing this too 🤔 but I don't want to make it possible that child classes misbehave (eg: making them return true for both isOk() and isErr())

But I just realized I can make the methods final instead of the whole class. I guess that could work. I'll give it a try

mathroc added a commit to mathroc/maybe that referenced this issue Jul 15, 2023
mathroc added a commit to mathroc/maybe that referenced this issue Jul 15, 2023
mathroc added a commit to mathroc/maybe that referenced this issue Jul 15, 2023
@mathroc
Copy link
Member

mathroc commented Jul 17, 2023

Hi @MattyRad, you can now extend Ok & Err, I have, however, marked all existing methods and the constructor as final to guarantee that subclasses can't change the desired behavior.

Please let me know if that works for you if you can try it!

@MattyRad
Copy link
Contributor Author

MattyRad commented Jul 17, 2023

Thanks, works great! If you're interested, here is a (redacted) snippet of how I'm using it:

<?php

use TH\Maybe;

/**
 * @template E
 *
 * @extends Maybe\Result\Err<E>
 * @implements MyClient\Result<never, E>
 */
final class Err extends Maybe\Result\Err implements MyClient\Result
{
    /**
     * @return self<MyHttpException>
     */
    private static function make(int $http_code, ?string $detail): self
    {
        $error = new MyHttpException(...[
            'http_code' => $http_code,
            'detail' => $detail,
        ]);

        return new self($error);
    }

    /**
     * @return self<MyHttpException>
     */
    public static function BAD_REQUEST(?string $detail = null): self
    {
        return self::make(400, $detail);
    }

    /**
     * @return self<MyHttpException>
     */
    public static function UNPROCESSABLE_ENTITY(?string $detail = null): self
    {
        return self::make(422, $detail);
    }

    /** more http codes ... */
}
/**
 * @return MyClient\Result<string, MyHttpException>
 */
public function resolve(MyClient\Request $request): MyClient\Result
{
    if (true /*or whatever */) {
        return new MyClient\Result\Ok("👍");
    }

    return Err::UNPROCESSABLE_ENTITY("It's wrong, yo.");
}
$result = $client->resolve($request);

// TODO: use some of the TH\Maybe\Result internal functions to remove the try/catch
try {
    $result = $result->unwrap();
} catch (MyHttpException) {
    $my_exception = $result->unwrapErr();
    $http_code = $my_exception->http_code; // No static analysis errors! Nice!
}

@mathroc
Copy link
Member

mathroc commented Jul 17, 2023

interesting :) thx for sharing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants