You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Eiffel中如何避免Catcall,直接比较类型而非借助非专用方法?

在Eiffel中无Catcall地比较类型相等(不依赖toString/class_id)

你遇到的Catcall问题根源在于is_equal的参数签名要求是like Current——当两个类型对象的泛型参数不同时,直接调用会因为类型不兼容触发Catcall。下面是两种不依赖类名字符串这类非专用方法的解决方案,完全利用Eiffel的类型系统特性来实现:

方案1:通过向上转型统一类型后调用is_equal

把两个类型对象都向上转换为TYPE[ANY],消除泛型参数带来的类型不匹配问题,这样调用is_equal时参数类型完全兼容,不会触发Catcall:

CLIENT_CLASS relationship_from_secondary_type_equal (a_type: like relationships.item.secondary_type): detachable like relationships.item -- 返回第一个次要类型与给定类型相等的关系实例
do
    across relationships as l_rel until Result /= Void loop
        -- 先确保类型对象非空,再统一转型为TYPE[ANY]后比较
        if attached {TYPE[ANY]}(a_type) as a_base_type and then
           attached {TYPE[ANY]}(l_rel.item.secondary_type) as rel_base_type and then
           a_base_type.is_equal (rel_base_type)
        then
            Result := l_rel.item
        end
    end
check
    not_found_relationship: Result /= Void
end

方案2:利用generating_type的单例特性比较

Eiffel中每个类对应唯一的generating_type实例,直接比较这个单例的引用相等性是更高效简洁的方式:

CLIENT_CLASS relationship_from_secondary_type_equal (a_type: like relationships.item.secondary_type): detachable like relationships.item -- 返回第一个次要类型与给定类型相等的关系实例
do
    across relationships as l_rel until Result /= Void loop
        -- 同一类的generating_type是同一个单例,直接用=比较即可
        if a_type.generating_type = l_rel.item.secondary_type.generating_type then
            Result := l_rel.item
        end
    end
check
    not_found_relationship: Result /= Void
end

为什么这些方案能解决问题?

  • 你之前尝试的a_type.is_equal(...)触发Catcall,是因为is_equal要求参数类型和Current完全一致(like Current),如果两个类型对象的泛型参数不同,就会出现类型不兼容。向上转型为TYPE[ANY]后,参数类型统一,就不会有这个问题。
  • generating_type返回的是类的核心类型单例,同一类的所有TYPE实例都会指向同一个generating_type对象,所以直接用=比较引用相等性就能准确判断类型是否一致,既高效又避免了类型不匹配的问题。

相比你之前用类名字符串的方式,这两种方案都是利用Eiffel类型系统的专用特性,更健壮、高效,也符合语言的设计意图。

内容的提问来源于stack exchange,提问作者Pipo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:50:17