Eiffel泛型参数约束双类时select子句编译语法错误排查
解决你的Eiffel泛型约束与
default_create调用问题 我来帮你拆解这个问题——首先你的泛型约束语法就写错了,这是编译器抛出语法错误的直接原因,其次我们再聊聊default_create的调用逻辑。
1. 泛型约束的语法错误根源
你原来的泛型约束写法:
G -> {IDENTIFIABLE[ANY], DB_ENTITY select default_create end}
这里的问题在于:select子句不能嵌套在单个父类的约束块里。在Eiffel的泛型规则中,select是一个顶层约束子句,用来解决多个父类之间的同名特征冲突,它需要放在所有父类约束的外面,而不是和某个父类绑定。
正确的约束写法
把select default_create移到整个约束集合的末尾,明确指定我们要保留default_create这个特征作为泛型G的强制接口:
G -> {IDENTIFIABLE[ANY], DB_ENTITY} select default_create end
这样编译器就能正确识别:G必须同时适配IDENTIFIABLE[ANY]和DB_ENTITY的接口,并且当这两个类都有default_create时,我们选择这个特征作为约束的一部分。
2. 为什么原语法会失败?
Eiffel的泛型约束语法中,{ClassA, ClassB}表示泛型参数必须同时满足这两个类的接口要求。而select子句是用来处理多父类之间的特征歧义的——它不属于某个单独的类,而是作用于整个约束集合。你原来把select嵌套在DB_ENTITY的大括号里,编译器无法解析这种非法的语法结构,所以直接报错。
3. 关于create Result的调用逻辑
当你修正泛型约束后,create Result就能正确触发G对应的default_create版本了:
- 约束已经明确要求
G必须提供default_create特征; - 如果
IDENTIFIABLE[ANY]和DB_ENTITY都定义了default_create,select子句会明确告诉编译器使用这个特征作为约束的一部分,不会产生歧义; - 运行时会自动调用
G实际类型对应的default_create实现,不管它是继承自哪个父类,或者有没有重命名/合并操作。
修正后的完整代码
deferred class IDENTIFIABLE_CASH[G -> {IDENTIFIABLE[ANY], DB_ENTITY} select default_create end] create default_create end inherit DB_SERVICE_CASH[G] feature -- Access cash_from_identifier (an_identifier: like {IDENTIFIABLE_DB_ENTITY[ANY]}.identifier): G -- Returns first entity found matching given an_identifier (using like operator) local l_qry: COMPOSED_SQL_QUERY do across cash is l_item loop if l_item.identifier.is_equal(an_identifier) then Result := l_item end end if not attached Result then create l_qry.make (item_prototype) l_qry.add_constraint (create {FIELD_CONSTRAINT}.make (Void, identifier_db_column_name, {CONSTRAINT}.Like_operator, an_identifier)) load_entities (l_qry) if items.count > 0 then Result := items.first else create Result check item_not_found: False end end cash.extend (Result) end end end
内容的提问来源于stack exchange,提问作者Pipo
相关产品推荐
相关产品推荐

