Eiffel: ошибка компиляции «Источник назначения несовместим с целью»

С полной проверкой недействительности, установленной в компиляторе, у меня есть ошибка компиляции «Переменная неправильно установлена» в следующем случае, что для меня правильно (на мой взгляд). Пишет, что источник назначения несовместим с целью. Что мне здесь не хватает??? (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

....

person Pipo    schedule 27.09.2018    source источник
comment
Этот пример безошибочно компилируется с EiffelStudio 18.07. Не могли бы вы уточнить, какую версию компилятора вы используете и с какими настройками, в частности, с какими настройками безопасности void?   -  person Alexander Kogtenkov    schedule 27.09.2018
comment
@AlexanderKogtenkov полностью переписал его, спасибо за вашу неоценимую помощь!   -  person Pipo    schedule 28.09.2018


Ответы (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
person Alexander Kogtenkov    schedule 28.09.2018
comment
в моем случае компилятор говорит что? GENERIC #1 =› ссылочный тип? что означает, что GENERIC # 2 будет расширен? почему объект Void типа NONE не соответствует GENERIC #1? говоря мой G -> DB_ENTITY Я уже сказал, что это ССЫЛКА, не так ли? - person Pipo; 28.09.2018
comment
На самом деле, если я делаю так, как вы указали (что, кажется, имеет смысл для меня), это работает, но почему это не работает по-моему???!!! - person Pipo; 28.09.2018
comment
@Pipo Формальный универсальный параметр может быть заменен как ссылочным, так и расширенным типом. Таким образом, код должен компилироваться для обоих случаев. Присвоение Void переменной допустимо, если переменная имеет отделяемый ссылочный тип, и недопустимо, если она имеет расширенный тип. Вот почему ваш код отклонен. Проверки выполняются один раз, когда класс компилируется, а не для каждого родового производного. - person Alexander Kogtenkov; 29.09.2018