如何获得枚举类型?

发布于 2025-01-27 12:55:12 字数 574 浏览 1 评论 0原文

我想知道获得枚举的后盾类型的最佳方法是什么:

enum E: string {
    case a = "A";
    case b = "B";
}

我有一个接收enum类名称为参数的函数,在函数中,我需要检查该类型是否由<<<代码> int 或字符串或不是后面的枚举

//this function can be called like: foo(E::class)
function foo(string $enum) {
    // here I need to check if $enum is backed by int or string or nothing
}

我已经尝试过get_parent_class,但是它不起作用,因为备份的枚举 s没有继承后背类型,它们只是封闭的列表。 我知道我可以在enum定义中放置一个静态功能,然后返回那里的类型,但是我想知道是否有更通用和优雅的方式?

I was wondering what is the best way to get an Enum's backed type:

enum E: string {
    case a = "A";
    case b = "B";
}

I have a function that receives an Enum class name as the parameter and inside the function I need to check if the type is backed by int or string or it is not a Backed Enum.

//this function can be called like: foo(E::class)
function foo(string $enum) {
    // here I need to check if $enum is backed by int or string or nothing
}

I've already tried get_parent_class, however it does not work since Backed Enums are not inheriting the back type and they are just closed lists.
I know I can put a static function inside the Enum definition and return the type there, but I was wondering if there is a more general and elegant way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

和影子一齐双人舞 2025-02-03 12:55:12

由于php 8.2,您可以使用 felfection> felfection

enum Foo: int {
    case Foo = 0;
}

enum Bar: string {
    case Bar = 'baz';
}

enum Baz {
    case Baz;
}

function get_backing_type(string $enum_class): ?string {
    return (new ReflectionEnum($enum_class))->getBackingType()?->getName();
}

function is_int_enum(string $enum_class): bool {
    return get_backing_type($enum_class) === 'int';
}

function is_string_enum(string $enum_class): bool {
    return get_backing_type($enum_class) === 'string';
}

$type = get_backing_type(Foo::class); // int
$type = get_backing_type(Bar::class); // string
$type = get_backing_type(Baz::class); // null

is_int_enum(Foo::class); // true
is_string_enum(Bar::class); // true

在行动中看到它

Since PHP 8.2 you can use reflection:

enum Foo: int {
    case Foo = 0;
}

enum Bar: string {
    case Bar = 'baz';
}

enum Baz {
    case Baz;
}

function get_backing_type(string $enum_class): ?string {
    return (new ReflectionEnum($enum_class))->getBackingType()?->getName();
}

function is_int_enum(string $enum_class): bool {
    return get_backing_type($enum_class) === 'int';
}

function is_string_enum(string $enum_class): bool {
    return get_backing_type($enum_class) === 'string';
}

$type = get_backing_type(Foo::class); // int
$type = get_backing_type(Bar::class); // string
$type = get_backing_type(Baz::class); // null

is_int_enum(Foo::class); // true
is_string_enum(Bar::class); // true

See it in action.

菊凝晚露 2025-02-03 12:55:12

对于任何寻求解决方案的人,这是 @Barmar建议的示例实现。

假设您的枚举至少有一个案例。

enum StringExample: string
{
    case foo = 'foo';
    case bar = 'bar';
}

/**
 * @param class-string<\BackedEnum> $enumClass
 *
 * @return array<int|string>
 */
 function getCaseValues(string $enumClass): array
 {
    return \array_map(
      static fn (\BackedEnum $case): int | string => $case->value,
      $enumClass::cases(),
    );
 }

$enumClass = StringExample::class;

$caseValues = getCaseValues($enumClass);

$isIntEnum = \is_int($this->caseValues[0] ?? null);
$isStringEnum = \is_string($this->caseValues[0] ?? null);

For anyone else looking for a solution, here's an example implementation of @Barmar's suggestion.

Assuming that your enum has at least a single case.

enum StringExample: string
{
    case foo = 'foo';
    case bar = 'bar';
}

/**
 * @param class-string<\BackedEnum> $enumClass
 *
 * @return array<int|string>
 */
 function getCaseValues(string $enumClass): array
 {
    return \array_map(
      static fn (\BackedEnum $case): int | string => $case->value,
      $enumClass::cases(),
    );
 }

$enumClass = StringExample::class;

$caseValues = getCaseValues($enumClass);

$isIntEnum = \is_int($this->caseValues[0] ?? null);
$isStringEnum = \is_string($this->caseValues[0] ?? null);
游魂 2025-02-03 12:55:12

仍然假设枚举至少有一个案例,这似乎更简单

/**
 * @template T of \BackedEnum
 * @param class-string<T> $enum
 * @return 'string'|'integer'
 */
function getEnumType(string $enumClass): ?string
{
    return gettype($enumClass::cases()[0]->value);
}

enum MyIntEnum: int
{
    case A = 1;
    case B = 2;
}
enum MyStringEnum: string
{
    case C = '1';
    case D = '2';
}

assert(getEnumType(MyIntEnum::class) === 'integer');
assert(getEnumType(MyStringEnum::class) === 'string');

Still assuming enums have atleast a single case, this seems simpler

/**
 * @template T of \BackedEnum
 * @param class-string<T> $enum
 * @return 'string'|'integer'
 */
function getEnumType(string $enumClass): ?string
{
    return gettype($enumClass::cases()[0]->value);
}

enum MyIntEnum: int
{
    case A = 1;
    case B = 2;
}
enum MyStringEnum: string
{
    case C = '1';
    case D = '2';
}

assert(getEnumType(MyIntEnum::class) === 'integer');
assert(getEnumType(MyStringEnum::class) === 'string');
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文