[英]Does Extern Break Encapsulation
I am new to C++ and I am creating a game.我是 C++ 的新手,我正在创建一个游戏。 I have a class called main in which I declare
我有一个名为 main 的类,我在其中声明
Game * game; //globally
int main() {
game = new Game();
game->show();
}
My class game initiates my game etc. Now in other classes (player, enemy, etc.), I access variables from the game such as player health using我的班级游戏启动我的游戏等。现在在其他班级(玩家、敌人等)中,我从游戏中访问变量,例如玩家健康使用
#include<game.h>
extern Game * game;
func::func() {
game->health->resetHealth();
}
Is this breaking encapsulation/ood paradigm?这是打破封装/ood 范式吗? Is it bad practice?
这是不好的做法吗? The thing is I can see any other way of doing it for a game.
问题是我可以看到任何其他的游戏方式。
Yes, extern
breaks encapsulation.是的,
extern
打破了封装。 The main concept of encapsulation is data hiding and binding property and behavior of an object in a single entity.封装的主要概念是将数据隐藏和绑定在单个实体中的对象的属性和行为。 Making the variable
extern
would break the law.使变量
extern
会违反法律。
In some more advance OOP
language like java
, there is no extern
.在一些更高级的
OOP
语言(如java
,没有extern
。 And in Java, it always suggested making property/field private to restrict its access.在 Java 中,它总是建议将属性/字段设为私有以限制其访问。
I mean, yeah, it's not encapsulated.我的意思是,是的,它没有封装。
game
is a global pointer that can be accessed and changed from anywhere. game
是一个全局指针,可以从任何地方访问和更改。 Encapsulation is about data hiding, and game
is totally exposed.封装就是数据隐藏,
game
完全暴露。 It is also not typical object-oriented design.它也不是典型的面向对象设计。 For proper encapsulation and OOD, you should restrict who uses and "knows about" the
Game * game
.为了正确封装和 OOD,您应该限制谁使用和“了解”
Game * game
。 For example, you can have a GameController
object that is composed of a Game *
.例如,您可以拥有一个由
Game *
组成的GameController
对象。 The scope and lifetime of the Game *
could live in GameController
, and then GameController
can encapsulate its member variable by making it private and deciding who, how and when the pointer is accessed. Game *
的范围和生命周期可以存在于GameController
,然后GameController
可以通过将其GameController
私有并决定访问指针的人、方式和GameController
来封装其成员变量。 There are other approaches, like wrapping the pointer in a global singleton class.还有其他方法,例如将指针包装在全局单例类中。 This is better than your example because the wrapping class can enforce certain invariants (like what should happen when the game is accessed, or how a client should delete a game).
这比您的示例要好,因为包装类可以强制执行某些不变量(例如访问游戏时应该发生什么,或者客户端应该如何删除游戏)。 Typically, global singletons are not the best approach for reasons outside of the scope of this answer.
通常,由于本答案范围之外的原因,全局单例不是最佳方法。 Another approach would be to use dependency injection.
另一种方法是使用依赖注入。 So, whenever a class needs to modify the
Game *
, it would have the pointer passed into it.因此,每当一个类需要修改
Game *
,它都会将指针传递给它。 These are all objected-oriented techniques for accessing encapsulated data.这些都是用于访问封装数据的面向对象技术。
Just having a global variable already starts breaking down your encapsulation because it provides access to the object from any code in your program.仅仅拥有一个全局变量就已经开始破坏您的封装,因为它提供了从程序中的任何代码访问对象的权限。 When you have a global like that any function can generate game-altering side effects, even ones in completely unrelated object instances.
当你有一个这样的全局变量时,任何函数都可以产生改变游戏的副作用,即使是在完全不相关的对象实例中也是如此。 Using extern doesn't break encapsulation any further because it's roughly equivalent to just pasting more code into the single source file that declared the global.
使用 extern 不会进一步破坏封装,因为它大致相当于将更多代码粘贴到声明全局的单个源文件中。
Using a global variable itself doesn't break encapsulation -- the object could hide its implementation details as much as it could if it were not global.使用全局变量本身不会破坏封装——如果对象不是全局变量,它可以尽可能多地隐藏其实现细节。 In most cases, it does, however, conflict with another design principle: flexibility.
然而,在大多数情况下,它确实与另一个设计原则相冲突:灵活性。 Say, you want your program to handle more than one game at a time (if such a later change doesn't make sense at all, you may decide to keep it global).
比如说,您希望您的程序一次处理多个游戏(如果这样的后期更改根本没有意义,您可以决定保持全局)。
Whenever you're about to declare some global variable, it's perhaps good to ask yourself:每当您要声明某个全局变量时,不妨问问自己:
game
object around to functions which need it.) game
对象传递给需要它的函数就很容易了。) In most cases, it's better to avoid global variables, in my opinion;在我看来,在大多数情况下,最好避免使用全局变量; and I think it's better to avoid it for the case shown in the question.
我认为对于问题中显示的情况最好避免它。 A
game
parameter can be passed around easily.可以轻松传递
game
参数。
In short, yes this breaks encapsulation.简而言之,是的,这打破了封装。 The fact that you keep referring to the game object reveals that you have dependencies towards this object.
您一直引用游戏对象这一事实表明您对这个对象有依赖性。
You might consider of having an initialisation sequence in your program, called the composition root, (for simple examples main is the most obvious place to do this), where you pass all dependencies like this towards the objects that need them via the constructor, which is called dependency injection.你可能会考虑在你的程序中有一个初始化序列,称为组合根,(对于简单的例子, main 是最明显的地方),在那里你通过构造函数将所有像这样的依赖传递给需要它们的对象,它称为依赖注入。
If you want to go even a step further you can create base classes and pass abstract base classes instead of implementation objects.如果您想更进一步,您可以创建基类并传递抽象基类而不是实现对象。 That way you are more programming towards interfaces instead of objects.
这样你就可以更多地针对接口而不是对象进行编程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.