承接 upscale/stdlib-overloading 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

upscale/stdlib-overloading

Composer 安装命令:

composer require upscale/stdlib-overloading

包简介

PHP7 function/method arguments overloading

README 文档

README

This library introduces function/method overloading – varying implementation depending on input arguments.

Features:

  • Overloading by argument types
  • Overloading by number of arguments
  • Efficient native type checks of PHP7
  • Informative native error messages of TypeError
  • Lightweight: no OOP, no Reflection

Installation

The library is to be installed via Composer as a dependency:

composer require upscale/stdlib-overloading

Usage

Syntax

Overload a custom function/method:

<?php
declare(strict_types=1);

use function Upscale\Stdlib\Overloading\overload;

function func(...$args)
{
    return overload(
        function (int $num1, int $num2) {
            // ...
        },
        function (string $str1, string $str2) {
            // ...
        }
        // ...
    )(...$args);
}

Any number of valid callable implementations can be declared. Order defines evaluation priority.

Call the overloaded function:

func(1, 2);
func('a', 'b');

Example

Arithmetic calculator that works with ordinary integers, arbitrary-length GMP integers, and Money objects.

<?php
declare(strict_types=1);

use function Upscale\Stdlib\Overloading\overload;

class Money
{
    private $amount;
    private $currency;

    public function __construct(int $amount, string $currency)
    {
        $this->amount = $amount;
        $this->currency = $currency;
    }

    public function add(self $sum): self
    {
        if ($sum->currency != $this->currency) {
            throw new \InvalidArgumentException('Money currency mismatch');
        }
        return new self($this->amount + $sum->amount, $this->currency);
    }
}

class Calculator
{
    public function add(...$args)
    {
        return overload(
            function (int $num1, int $num2): int {
                return $num1 + $num2;
            },
            function (\GMP $num1, \GMP $num2): \GMP {
                return gmp_add($num1, $num2);
            },
            function (Money $sum1, Money $sum2): Money {
                return $sum1->add($sum2);
            }
        )(...$args);
    }
}


$calc = new Calculator();

$one = gmp_init(1);
$two = gmp_init(2);

$oneUsd = new Money(1, 'USD');
$twoUsd = new Money(2, 'USD');

print_r($calc->add(1, 2));
// 3

print_r($calc->add($one, $two));
// GMP Object([num] => 3)

print_r($calc->add($oneUsd, $twoUsd));
// Money Object([amount:Money:private] => 3 [currency:Money:private] => USD)

print_r($calc->add(1.25, 2));
// TypeError: Argument 1 passed to Calculator::{closure}() must be an instance of Money, float given

Architecture

The overloading mechanism leverages the native type system of PHP7 and relies on declaration of strict type annotations. It traverses implementation callbacks in the declared order and attempts to invoke each of them with provided arguments. Result of the first compatible invocation is returned and the subsequent callbacks discarded.

Limitations

PHP engine allows to pass more runtime arguments to a function/method than accounted for in its signature declaration. Excess arguments are being silently discarded without triggering any catchable errors, not even ArgumentCountError. The solution is to declare more specific longer signatures before less specific ones with matching subset of arguments.

Optional arguments are problematic as they are call-time compatible with a shorter signature of required arguments only. Consider the following ambiguous declaration that cannot be resolved by reordering:

overload(
    function (int $num1, int $num2) {
        // ... 
    },
    function (int $num1) {
        // ... 
    },
    function (int $num1, string $str2 = 'default') {
        // Unreachable because preceding declaration matches first and swallows excess arguments
        // ...
    }
)

The workaround is to validate the number of arguments to not exceed the declaration:

overload(
    function (int $num1, int $num2) {
        // ... 
    },
    function (int $num1) {
        if (func_num_args() > 1) {
            throw new \ArgumentCountError('Too many arguments provided');
        }
        // ... 
    },
    function (int $num1, string $str2 = 'default') {
        // Reachable with the optional argument passed, but still unreacable without it
        // ... 
    }
)

Contributing

Pull Requests with fixes and improvements are welcome!

License

Copyright © Upscale Software. All rights reserved.

Licensed under the Apache License, Version 2.0.

统计信息

  • 总下载量: 3
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 3
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: Apache-2.0
  • 更新时间: 2020-02-13

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固