Trong trường hợp này, tôi muốn nói câu trả lời lý tưởng là nó phụ thuộc vào cách thức các enum được tiêu thụ, nhưng trong hầu hết các trường hợp, có lẽ tốt nhất là xác định tất cả các enum riêng biệt, nhưng nếu bất kỳ trong số chúng đã được ghép bởi thiết kế, bạn nên cung cấp một phương tiện giới thiệu nói chung ghép enums. Trong thực tế, bạn có một dung sai khớp nối lên đến số lượng khớp nối có chủ ý đã có, nhưng không còn nữa.
Xem xét điều này, giải pháp linh hoạt nhất có khả năng xác định từng enum trong một tệp riêng biệt, nhưng cung cấp các gói được ghép khi hợp lý để làm như vậy (như được xác định bởi mục đích sử dụng của enum liên quan).
Xác định tất cả các liệt kê của bạn trong cùng một tệp kết hợp chúng với nhau và bởi phần mở rộng gây ra bất kỳ mã nào phụ thuộc vào một hoặc nhiều enum phụ thuộc vào tất cả các enum, bất kể mã đó có thực sự sử dụng bất kỳ enum nào khác không.
#include "enumList.h"
// Draw map texture. Requires map_t.
// Not responsible for rendering entities, so doesn't require other enums.
// Introduces two unnecessary couplings.
void renderMap(map_t, mapIndex);
renderMap()
thay vì chỉ biết về nó map_t
, bởi vì nếu không thì mọi thay đổi đối với người khác sẽ ảnh hưởng đến nó mặc dù nó không thực sự tương tác với những người khác.
#include "mapEnum.h" // Theoretical file defining map_t.
void renderMap(map_t, mapIndex);
Tuy nhiên, trong trường hợp các thành phần đã được ghép nối với nhau, việc cung cấp nhiều enum trong một gói có thể dễ dàng cung cấp thêm sự rõ ràng và đơn giản, miễn là có một lý do hợp lý rõ ràng cho các enum được ghép nối, việc sử dụng các enum đó cũng được ghép nối, và việc cung cấp cho họ cũng không giới thiệu bất kỳ khớp nối bổ sung nào.
#include "entityEnum.h" // Theoretical file defining entity_t.
#include "materialsEnum.h" // Theoretical file defining materials_t.
// Can entity break the specified material?
bool canBreakMaterial(entity_t, materials_t);
Trong trường hợp này, không có kết nối trực tiếp, hợp lý giữa loại thực thể và loại vật liệu (giả sử rằng các thực thể không được làm từ một trong các vật liệu được xác định). Tuy nhiên, nếu chúng ta gặp trường hợp, ví dụ, một enum rõ ràng phụ thuộc vào nhau, thì việc cung cấp một gói duy nhất chứa tất cả các enum ghép (cũng như bất kỳ thành phần ghép nào khác), để khớp nối có thể cô lập với gói đó càng nhiều càng tốt.
// File: "actionEnums.h"
enum action_t { ATTACK, DEFEND, SKILL, ITEM }; // Action type.
enum skill_t { DAMAGE, HEAL, BUFF, DEBUFF, INFLICT, NONE }; // Skill subtype.
// -----
#include "actionTypes.h" // Provides action_t & skill_t from "actionEnums.h", and class Action (which couples them).
#include "entityEnum.h" // Theoretical file defining entity_t.
// Assume ActFlags is or acts as a table of flags indicating what is and isn't allowable, based on entity_t and Action.
ImplementationDetail ActFlags;
// Indicate whether a given type of entity can perform the specified action type.
// Assume class Action provides members type() and subtype(), corresponding to action_t and skill_t respectively.
// Is only slightly aware of the coupling; knows type() and subtype() are coupled, but not how or why they're coupled.
bool canAct(entity_t e, const Action& act) {
return ActFlags[e][act.type()][act.subtype()];
}
Nhưng than ôi ... ngay cả khi hai enum thực chất được ghép với nhau, ngay cả khi nó là thứ gì đó mạnh như "enum thứ hai cung cấp các thể loại con cho enum đầu tiên", vẫn có thể đến lúc chỉ cần một trong số các enum.
#include "actionEnums.h"
// Indicates whether a skill can be used from the menu screen, based on the skill's type.
// Isn't concerned with other action types, thus doesn't need to be coupled to them.
bool skillUsableOnMenu(skill_t);
// -----
// Or...
// -----
#include "actionEnums.h"
#include "gameModeEnum.h" // Defines enum gameMode_t, which includes MENU, CUTSCENE, FIELD, and BATTLE.
// Used to grey out blocked actions types, and render them unselectable.
// All actions are blocked in cutscene, or allowed in battle/on field.
// Skill and item usage is allowed in menu. Individual skills will be checked on attempted use.
// Isn't concerned with specific types of skills, only with broad categories.
bool actionBlockedByGameMode(gameMode_t mode, action_t act) {
if (mode == CUTSCENE) { return true; }
if (mode == MENU) { return (act == SKILL || act == ITEM); }
//assert(mode == BATTLE || mode == FIELD);
return false;
}
Do đó, vì chúng ta biết cả hai luôn có thể có các tình huống xác định nhiều cách liệt kê trong một tệp có thể thêm khớp nối không cần thiết và việc cung cấp các enum ghép trong một gói có thể làm rõ cách sử dụng dự định và cho phép chúng ta tự cô lập mã khớp nối thực tế như càng nhiều càng tốt, giải pháp lý tưởng là xác định riêng từng kiểu liệt kê và cung cấp các gói chung cho bất kỳ enum nào được dự định thường xuyên được sử dụng cùng nhau. Các enum duy nhất được xác định trong cùng một tệp sẽ là những cái được liên kết nội tại với nhau, như vậy việc sử dụng cái này cũng bắt buộc phải sử dụng cái kia.
// File: "materialsEnum.h"
enum materials_t { WOOD, STONE, ETC };
// -----
// File: "entityEnum.h"
enum entity_t { PLAYER, MONSTER };
// -----
// File: "mapEnum.h"
enum map_t { 2D, 3D };
// -----
// File: "actionTypesEnum.h"
enum action_t { ATTACK, DEFEND, SKILL, ITEM };
// -----
// File: "skillTypesEnum.h"
enum skill_t { DAMAGE, HEAL, BUFF, DEBUFF, INFLICT, NONE };
// -----
// File: "actionEnums.h"
#include "actionTypesEnum.h"
#include "skillTypesEnum.h"