方法未找到回退

发布: (2026年2月17日 GMT+8 23:22)
5 分钟阅读
原文: Dev.to

Source: Dev.to

请提供您想要翻译的正文内容,我将按照要求保留源链接并将其余部分翻译成简体中文。

Overview

This is part eleven in the Cases of UPPER series, describing the Raku syntax elements that are completely in UPPERCASE.
In this part we discuss the interface method that can be provided in a class to handle calls to methods that do not actually exist in the class (or its parents).

Raku 中的方法查找

Raku 编程语言中的方法分派相当复杂,尤其是多重分派(multi‑dispatch)。第一步是检查是否存在具有给定名称的(多重)方法。内部实现是通过类的元对象(meta‑object)上的 find_method 方法完成的(通常使用 .^method 语法调用)。

# an empty class
class A { }

dd A.^find_method("foobar");  # Mu
dd A.^find_method("gist");    # proto method gist (Mu $:: |) {*}

一个空类 A(继承自 Any)不提供 foobar 方法(由 Mu 类型对象表示),但它确实提供了 gist 方法(从 Any 继承而来)。

如果分派逻辑无法根据给定名称找到方法,就会抛出 X::Method::NotFound 错误。可以使用 CATCH 相位捕获此类情况,但还有一种更简洁、更符合惯用法的方式:FALLBACK 方法。

FALLBACK 方法

当一个类提供 FALLBACK 方法(直接、通过继承或通过角色)时,只要找不到方法就会调用该方法。缺失的方法名作为第一个参数传入,其他所有参数原样传递。

简单示例

class B {
    method FALLBACK($name) { $name }
}

say B.foo;      # foo
say B.bar(42);  # Too many positionals passed; expected 2 arguments but got 3

多方法 FALLBACK

class C {
    multi method FALLBACK($name) {
        $name
    }
    multi method FALLBACK($name, $value) {
        "$value.raku() passed to '$name'"
    }
}

say C.foo;      # foo
say C.bar(42);  # 42 passed to 'bar'

忽略参数

如果你不关心任何参数,只想返回 Nil,可以使用无名捕获 (|) 作为签名:

class D {
    method FALLBACK(|) { Nil }
}

say D.foo;      # Nil
say D.bar(42);  # Nil

使用 FALLBACK 修正下划线/连字符错误

Raku 允许在标识符名称中使用连字符(kebab case)。来自其他语言的程序员常常错误地使用下划线(snake case),这会导致运行时错误。FALLBACK 方法可以拦截这些错误并进行修正。

class E {
    method foo-bar() { "foobar" }

    method FALLBACK($name, |c) {
        my $corrected = $name.trans("_" => "-");
        if self.^find_method($corrected, :no_fallback) -> &code {
            code(self, |c)
        }
        else {
            X::Method::NotFound.new(
                :invocant(self), :method($name), :typename(self.^name)
            ).throw;
        }
    }
}
  • foo-bar 是一个合法的方法。
  • FALLBACK 方法接收缺失的方法名($name)以及任何额外的参数(|c)。
  • 它将下划线替换为连字符,使用 .^find_method 并加上 :no_fallback(以避免递归调用 fallback)查找修正后的名称;如果找到,则使用原始参数调用该方法。
  • 如果不存在相应的修正方法,则重新抛出 Method::NotFound 错误。
say E.foo-bar;  # foobar
say E.foo_bar;  # foobar

可复用的角色:Method::Misspelt

上述逻辑可以封装成一个角色并作为模块分发。这导致了 Method::Misspelt 角色的创建,该角色提供相同的功能,并为多个使用该角色的类提供额外的特性和优化。详情请参阅模块的内部文档。

结论

本期介绍了 FALLBACK 方法,演示了多种自定义方式,并展示了一个用于纠正下划线到连字符错误的实际案例。作为本博客文章的延伸,创建了一个额外模块 Method::Misspelt

敬请期待下一期!

0 浏览
Back to Blog

相关文章

阅读更多 »

存储代理获取

UPPER 案例 – 第12部分 Raku 中的容器 这是 UPPER 系列的第12部分,记录了 Raku 语法元素的完整写法……

学习 C# 的第 -1 天

入门 今天,我正式开始了我的 C 之旅——不是从高级主题,而是从最基础的内容开始。在构建复杂的应用程序之前,我想…