Поскольку для действия gen
требуется только один gen-item
, необходимо сгруппировать две переменные, которые вы хотите решить вместе. Вы можете сделать это, определив новый struct
:
struct IpVersionInfo {
Ipv4En: bool;
Ipv6En: bool;
keep Ipv4En == TRUE or Ipv6En == TRUE;
};
Вместо двух переменных для включений вы используете одну переменную этого нового struct
типа:
struct MyStruct {
!ipVersionInfo: IpVersionInfo;
MyMethod() is {
gen ipVersionInfo;
};
};
Если вы выполните пару итераций, вы увидите, что можете достичь всех комбинаций:
extend sys {
run() is also {
for i from 1 to 20 {
var s: MyStruct = new;
s.MyMethod();
outf(
"Ipv4En = %s, Ipv6En = %s\n",
s.ipVersionInfo.Ipv4En,
s.ipVersionInfo.Ipv6En);
};
};
};
Это требует изменения API, поэтому вам нужно обновить весь код, на который ссылаются Ipv4En
и Ipv6En
.
Помимо группировки двух полей в struct
, есть и другие способы решения вашей проблемы. Другим примером может быть определение enum
, которое содержит значения для ваших юридических случаев:
type ip_version_info_e: [ V4, V6, BOTH ];
Как и раньше, вы можете использовать переменную этого типа в вашем struct
:
struct MyStruct {
!ip_version_info: ip_version_info_e;
MyMethod() is {
gen ip_version_info;
};
};
Если вы выполните пару итераций нового кода, вы увидите, что он также достигает всех возможных комбинаций:
extend sys {
run() is also {
for i from 1 to 20 {
var s: MyStruct = new;
s.MyMethod();
outf(
"Ipv4En = %s, Ipv6En = %s\n",
s.ip_version_info in [ V4, BOTH ],
s.ip_version_info in [ V6, BOTH ]);
};
};
};
Независимо от того, как вы решили решить проблему, вы должны скрывать внутреннюю реализацию от любого клиентского кода, который использует MyStruct
. Обратите внимание, что операторы out
сверху выглядят по-разному в зависимости от того, как мы решили обрабатывать настройки IP-версии. Вместо того, чтобы клиентский код заглядывал слишком глубоко внутрь MyStruct
, вы должны определить следующие два метода:
isIpv4Enabled(): bool;
isIpv6Enabled(): bool;
В случае, когда мы сгруппировали две логические переменные в struct
, реализации этих двух методов:
struct MyStruct {
// ...
isIpv4Enabled(): bool is {
result = ipVersionInfo.Ipv4En;
};
isIpv6Enabled(): bool is {
result = ipVersionInfo.Ipv6En;
};
};
В случае, когда мы определили enum
, мы имеем:
struct MyStruct {
// ...
isIpv4Enabled(): bool is {
result = ip_version_info in [ V4, BOTH ];
};
isIpv6Enabled(): bool is {
result = ip_version_info in [ V6, BOTH ];
};
};
В обоих случаях клиентский код для печати будет одинаковым:
extend sys {
run() is also {
for i from 1 to 20 {
var s: MyStruct = new;
s.MyMethod();
outf(
"Ipv4En = %s, Ipv6En = %s\n",
s.isIpv4Enabled(),
s.isIpv4Enabled());
};
};
};
Это главное преимущество. Таким образом, вы можете в будущем изменить реализацию MyStruct
и не трогать какой-либо другой код, который ее использует.