явный тип создания, не соответствующий типу цели - PullRequest
0 голосов
/ 14 октября 2019

Я действительно не понимаю, как мне кажется, основы соответствия типов. У меня есть Creation instruction lists explicit creation type which does not conform to type of target на create {JANITZA_DEVICE} l_device.make_from_file_path (a_file_path) с eiffel studio 19.5.

class schema

SMA_INVERTER_MANAGER_CSV

class
    SMA_INVERTER_MANAGER_CSV

inherit
    SUNSPEC_DEVICE_CSV[SMA_INVERTER_MANAGER_DEVICE]

create
    make

SUNSPEC_DEVICE_CSV

deferred class
    SUNSPEC_DEVICE_CSV[G -> SUNSPEC_DEVICE create make_from_file_path end]

inherit
    CONSUMPTION_SECTOR_CSV[G]
        redefine
            process_file,
            set_header_csv
        end

feature --

    process_file (a_file_path: PATH)
        require else
            attached a_file_path.entry
            attached consumption_sector
        local
            l_device: like devices.item
        do
            check
                attached_consumption_sector: attached consumption_sector
            then
                if is_valid_file_path (a_file_path) then
                    if attached a_file_path.utf_8_name.has_substring ("janitza_UMG604") then
                        create {JANITZA_DEVICE} l_device.make_from_file_path (a_file_path) -- The compiler doesn't agree!
                    else
                        create l_device.make_from_file_path (a_file_path)
                    end
                    l_device.load_measuring_point (create_measuring_points, measuring_point_db_service, consumption_sector)
                    devices.extend (l_device)
                    Precursor (a_file_path) -- load measure_units from csv_row
                    devices.wipe_out
                end
            end
        ensure then
            devices.is_empty
        end

CONSUMPTION_SECTOR_CSV [G]

deferred class
    CONSUMPTION_SECTOR_CSV[G -> MEASURING_POINT_DEVICE]

feature -- Access

    devices: LINKED_SET[G]

SUNSPEC_DEVICE

class
    SUNSPEC_DEVICE

inherit
    MEASURING_POINT_DEVICE
        redefine
            default_create,
            set_measuring_point,
            out
        select
            serial
        end

    MODBUS_DEVICE
        rename
            serial as modbus_serial,
            set_serial as set_modbus_serial
        undefine
            make
        redefine
            default_create,
            make_from_file_path,
            name_from_file_path,
            out
        select
            set_modbus_serial
        end

create
    make_from_file_path

JANITZA_DEVICE

class
    JANITZA_DEVICE

inherit
    SUNSPEC_DEVICE
        redefine
            set_measure_units,
            name_from_file_path
        end

create
    make_from_file_path

Ответы [ 2 ]

2 голосов
/ 14 октября 2019

Вот упрощенный случай:

class ANIMAL

class CAT inherit ANIMAL

class HOUSE_CAT inherit CAT

class DOG inherit ANIMAL
class
    ENCLOSURE [G -> ANIMAL]
feature
    specimens: LIST [G] --> The actual type will vary with the generic parameter

    describe
        do
            print(specimens.generating_type)
        end
class
    APPLICATION

feature

    test
        local
            l_cat: CAT
            l_animal_enclosure: ENCLOSURE [ANIMAL]
            l_cat_enclosure: ENCLOSURE [CAT]
            l_house_cat_enclosure: ENCLOSURE [HOUSE_CAT]
            l_dog_enclosure: ENCLOSURE [DOG]
        do
            create l_specimen

            create l_animal_enclosure
            l_animal_enclosure.describe --> LIST [ANIMAL]
            l_animal_enclosure.specimens.add (l_cat) --> Fine, CAT conforms to ANIMAL

            create l_cat_enclosure
            l_cat_enclosure.describe --> LIST [CAT]
            l_cat_enclosure.specimens.add (l_cat) --> Fine, CAT conforms to CAT

            create l_house_cat_enclosure
            l_house_cat_enclosure.describe --> LIST [HOUSE_CAT]
            l_house_cat_enclosure.specimens.add (l_cat) --> ERROR, CAT does not conform to HOUSE_CAT


            create l_dog_enclosure
            l_dog_enclosure.describe --> LIST [DOG]
            l_dog_enclosure.specimens.add (l_cat) --> ERROR, CAT does not conform to CAT
        end

В вашем случае devices: LINKED_SET [G] слишком расплывчато, ничто не доказывает, что JANITZA_DEVICE является допустимым типом, потому что G можетв конечном итоге ниже по иерархии (как HOUSE_CAT -> CAT; вы не можете заменить CAT на HOUSE_CAT, таким образом, список HOUSE_CAT не может вместить CAT) или в отдельной ветвииерархии (например, DOG -> ANIMAL; собака не является кошкой, они имеют общего предка).

Если {ENCLOSURE}.specimens был объявлен как LIST [ANIMAL] вместо LIST [G], describe всегда будет печатать LIST [ANIMAL] независимо от фактического универсального параметра, потому что тип не будет меняться, поэтому предыдущий код будет компилироваться и работать просто отлично. Точно так же, если {CONSUMPTION_SECTOR_CSV}.devices был объявлен как LINKED_SET [SUNSPEC_DEVICE] вместо LINKED_SET [G], он мог бы вместить всех потомков SUNSPEC_DEVICE независимо от фактического типа G.

В качестве альтернативы, вы могли бы перемещать деталиспецифично для JANITZA_DEVICE от CONSUMPTION_SECTOR_CSV до потомка CONSUMPTION_SECTOR_CSV, где G закрыто, как в

class
    JANITZA_CONSUMPTION_SECTOR_CSV -- No generic here!
inherit
    CONSUMPTION_SECTOR_CSV [JANITZA_DEVICE]
        redefine
            process_file -- Add the parts specific to `JANITZA_DEVICE` in the implementation
        end

, что гарантирует, что devices может содержать экземпляры JANITZA_DEVICE.

0 голосов
/ 15 октября 2019

Я думаю, что пользователь 10481525 объяснил причину ошибки. Ваш код не гарантирует, что JANITZA_DEVICE будет соответствовать G во всех потенциальных потомках SUNSPEC_DEVICE_CSV.

Вы объявили атрибут devices: LINKED_SET [G]. Следовательно, локальная переменная l_device: like devices.item будет иметь тип G. Присоединение JANITZA_DEVICE к нему может быть недопустимым для потомка SUNSPEC_DEVICE_CSV. Почему? Поскольку G может быть любым потомком SUNSPEC_DEVICE.

Например, предположим, что у вас есть потомок class FOO_DEVICE_CSV inherit SUNSPEC_DEVICE_CSV [FOO_DEVICE];где class FOO_DEVICE inherit SUNSPEC_DEVICE. Ваша локальная переменная будет эффективно преобразована в local l_device: FOO_DEVICE. Следовательно, потомок будет пытаться прикрепить к нему объект типа JANITZA_DEVICE. Но это неверно, потому что JANITZA_DEVICE не соответствует FOO_DEVICE:

feature devices: LINKED_SET [FOO_DEVICE] ... local l_device: FOO_DEVICE ... create {JANITZA_DEVICE} l_device.make_from_file_path (a_file_path) -- Invalid!

...