显式创建类型不符合目标类型
explicit creation type not conforming to type of target
我真的不明白类型一致性的基础知识。我在 create {JANITZA_DEVICE} l_device.make_from_file_path (a_file_path)
上有一个 Creation instruction lists explicit creation type which does not conform to type of target
和 eiffel studio 19.5 enterprise。
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
这是一个简化的案例:
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 DOG
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
.[=41 的实际类型=]
或者,您可以将特定于 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
。
我想user10481525已经解释了错误的原因。您的代码不保证 JANITZA_DEVICE
在 SUNSPEC_DEVICE_CSV
.
的所有潜在后代中都符合 G
您已声明属性 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!
我真的不明白类型一致性的基础知识。我在 create {JANITZA_DEVICE} l_device.make_from_file_path (a_file_path)
上有一个 Creation instruction lists explicit creation type which does not conform to type of target
和 eiffel studio 19.5 enterprise。
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
这是一个简化的案例:
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 DOG
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
.[=41 的实际类型=]
或者,您可以将特定于 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
。
我想user10481525已经解释了错误的原因。您的代码不保证 JANITZA_DEVICE
在 SUNSPEC_DEVICE_CSV
.
G
您已声明属性 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!