【问题标题】:Eiffel: compilation error `Source of assignment is not compatible with target`埃菲尔:编译错误`分配源与目标不兼容`
【发布时间】:2018-09-27 13:43:09
【问题描述】:

在编译器中设置了完整的 void 检查后,我在以下情况下出现了一个变量未正确设置编译错误,这对我来说是正确的(在我看来)。它说分配的来源与目标不兼容。我在这里想念什么??? (DB_SERVICE.load_from_primary_key...)

类 DB_SERVICE

deferred class
    DB_SERVICE [G -> DB_ENTITY create make_from_db_result end]

inherit
    ACTION
        redefine
            start,
            execute
        end

    LOGGABLE
        rename
            make as make_from_loggable
        end

feature -- Creation

    make (a_db_connection: attached DB_CONNECTION)
        require
            valid_db_connection: a_db_connection.is_connected
        do
            make_from_loggable
            db_connection := a_db_connection
            create last_items.make (100)
            create last_column_names.make_empty
        ensure
            db_connection_setted: a_db_connection = db_connection and db_connection.is_connected
        end

feature -- Access

    item: detachable G

    db_connection: DB_CONNECTION

    last_items: HASH_TABLE[like item, INTEGER] -- content of last resultset

    last_column_names: ARRAY[STRING] -- Column names of last resultset

feature -- status_report


    load_from_primary_key (primary_key: INTEGER)
            -- Loads given item into item otherwise item will be Void
        require
            attached db_connection.base_selection
        local
            l_db_result: DB_RESULT
        do
            if attached db_connection.base_selection as bs then
                bs.query ("SELECT * FROM " + ({attached like item}).out + " WHERE " + {attached like item}.Primary_key_db_column_name + "=" + primary_key.out)
                if bs.is_ok then
                    bs.load_result
                    create item.make_from_db_result(last_column_names, bs.cursor)
                else
                    item := Void --HERE is the compiler complaining!
                    logger.write_critical ("Error while retreiving " + ({like item}).out + " from DB")
                end
            else
                item := Void 
                logger.write_error ("base_selection is void")
            end
        end


end -- class

类 COMPANY_SERVICE

class
    COMPANY_SERVICE

inherit
    DB_SERVICE[COMPANY]
        redefine
            make
        end
...

类公司

class
    COMPANY

inherit
    DB_ENTITY
        rename
            primary_key as id,
            set_primary_key as set_id,
            Primary_key_db_column_name as Id_db_column_name
        redefine
            make,
            make_from_db_result,
            out
        end

create
    make,
    make_from_db_result

....

【问题讨论】:

  • 本示例使用 EiffelStudio 18.07 编译时没有任何错误。您能否澄清一下您正在使用哪个编译器版本以及使用哪些设置,特别是使用哪些 void 安全设置?
  • @AlexanderKogtenkov 完全重写了它,感谢您提供的所有宝贵帮助!

标签: eiffel void-safety


【解决方案1】:

类型声明detachable G 表示如果对应的实际泛型是引用类型,则该类型的变量可以是可分离的。在这种情况下,可以将Void 分配给这样的变量。但是,实际的泛型也可能是扩展类型。扩展类型前缀detachable 无效,类型保持不变,变量不能赋值Void。

作为一个例子,让我们考虑一个更简单的情况,当参数G 没有正式的通用约束时。一个实际的泛型可能是STRING,而变量item 的类型是detachable STRING。在这种情况下,可以将Void 分配给item。

现在,如果实际的泛型是 INTEGER,则变量的类型为 detachable INTEGER,它等价于 INTEGER。将Void 分配给这种类型的变量是没有意义的,并且是语言规则所不允许的。

如果实际的泛型参数是引用类型,变量item 仍然可以设置为Void。为此,可以声明一个相同类型的局部变量,并将其值赋值给item:

local
    default_item: like item
do
    item := default_item

【讨论】:

  • 就我而言,编译器在说什么? GENERIC #1 => 参考类型?这意味着 GENERIC #2 将被扩展?为什么 NONE 类型的 Void“对象”不符合 GENERIC #1?说我的 G -> DB_EN​​TITY 我已经说它是 REFERENCE 不是吗?
  • 实际上,如果我确实像您指定的那样(这在某种程度上对我来说似乎很有意义),它可以工作,但为什么它不能按我的方式工作???!!!
  • @Pipo 正式的泛型参数可以用引用类型和扩展类型替换。因此,代码应该为这两种情况编译。如果变量是可拆卸引用类型,则将Void 分配给变量是可以的,如果是扩展类型,则不可以。这就是您的代码被拒绝的原因。检查只在编译类时执行一次,而不是针对每个泛型派生。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-08
  • 2018-12-11
  • 1970-01-01
相关资源
最近更新 更多