防止破坏封装(Prevent breaking encapsulation)

编程入门 行业动态 更新时间:2024-10-27 20:32:00
防止破坏封装(Prevent breaking encapsulation)

我有这堂课:

class Phone { private: string producer, color; int weight, dimension; public: Phone(string &producer, string &color, int &weight, int &dimension): producer(producer), color(color), weight(weight), dimension(dimension) {}; Phone(): producer(""), color(""), weight(0), dimension(0) {}; virtual ~Phone() {}; string getProducer(void) const; string getColor(void) const; int getWeight(void) const; int getDimension(void) const; virtual void displayInfo(void) const; };

这里的问题是由于我通过getter公开对象的内部实现。

但是我该如何防止这种情况呢?

因为通常在我的代码中,我需要知道来自我的对象的一些私有数据(比较是一个例子),这就是我使用getter的原因。

那么我将类重写为以下内容:

class Phone { private: string producer, color; int weight, dimension; public: Phone(string &producer, string &color, int &weight, int &dimension): producer(producer), color(color), weight(weight), dimension(dimension) {}; Phone(): producer(""), color(""), weight(0), dimension(0) {}; virtual ~Phone() {}; bool isTheProducer(string& producer) const { return this->producer == producer }; bool hasWeight(int& weight) const { return this->weight == weight }; bool hasDimension(int& dimension) const { return this->dimension == dimension }; virtual void displayInfo(void) const; };

这是一个更好的设计(因为我没有得到实际的私人价值)?

I have this class:

class Phone { private: string producer, color; int weight, dimension; public: Phone(string &producer, string &color, int &weight, int &dimension): producer(producer), color(color), weight(weight), dimension(dimension) {}; Phone(): producer(""), color(""), weight(0), dimension(0) {}; virtual ~Phone() {}; string getProducer(void) const; string getColor(void) const; int getWeight(void) const; int getDimension(void) const; virtual void displayInfo(void) const; };

The problem is here caused by the fact that I expose the internal implementation of the object via getters.

But how can I prevent this?

Because usually in my code, I need to know some private data from my object (for comparision is one example), and that's why I use getters.

So then I rewrite the class to something like this:

class Phone { private: string producer, color; int weight, dimension; public: Phone(string &producer, string &color, int &weight, int &dimension): producer(producer), color(color), weight(weight), dimension(dimension) {}; Phone(): producer(""), color(""), weight(0), dimension(0) {}; virtual ~Phone() {}; bool isTheProducer(string& producer) const { return this->producer == producer }; bool hasWeight(int& weight) const { return this->weight == weight }; bool hasDimension(int& dimension) const { return this->dimension == dimension }; virtual void displayInfo(void) const; };

Is this a better design (by the fact that I don't get the actual private value)?

最满意答案

正如您可能从其他答案和评论中看到的那样,答案是:这取决于。

实际上,它主要取决于使用类的用例。 让我们先来看问题中给出的例子,对象的比较。 由于我们想要比较两个电话对象或仅仅是一个特定的数据成员,从问题中看不清楚,我将在这里讨论这两种情况。

将数据成员与类外数据进行比较

让我们在这个用例中搜索重量大于x(只是伪代码)的所有手机:

for (Phone& p in phoneList) { if (p.getWeight() > x) { cout << "Found"; } }

然后第一类示例非常好,因为这不是手机的固有功能,因此手机类不负责处理它。 此外,结果不会暴露超出任务绝对必需的范围。

比较两个手机对象

在这种情况下,两个代码示例同样好(或者在这种情况下同样糟糕)。 在这两种情况下,用户必须知道有关如何表示电话以比较所有必要成员的许多细节。 如果在以后的版本中将新成员添加到类中,则必须调整比较两个电话的每个代码段。 为了克服这个问题,可以在完全比较的类中添加一个函数。

class Phone { private: string producer, color; int weight, dimension; public: bool IsEqualTo(const Phone& other) { return (producer == other.producer && color == other.color &&....); }

非比较用例

但让我们来看一个更高级的例子。 让我们假设以下任务:用户将引脚输入手机,如果是正确的,则手机应解锁。 让我们假设一个非常天真的方法:

class Phone { private: int pin; bool unlocked; public: int getPin() { return pin; } void unlock() { unlocked = true; } };

和相应的电话

if (phone.getPin() == enteredPin) phone.unlock();

在这种情况下,我们有一个完全不同的情况。 在这里,我们需要考虑“告诉,不要问”规则,这基本上说,首先查询对象的状态,做出决定然后告诉对象该做什么是一个糟糕的设计。 相反,我们应该只告诉对象我们想要什么,并让它为我们工作。 在这个用例中,这是显而易见的,因为只有在引脚正确时解锁电话才是电话的责任,而不是使用电话类的用户的责任。 但在更复杂的情况下,许多程序员将完全按照我在此描述的那样做。

回到问题:这里的一个好解决方案就是

class Phone { private: int pin; bool unlocked; public: void CheckPin(int enteredPin) { if (pin == enteredPin) unlocked = true; } };

与代码

phone.CheckPin(enteredPin);

希望这会有所帮助,并感谢@KonradRudolph指出“告诉,不要问规则”。 随意帮我改进每个评论的答案:)

As you might have seen from the other answers and comments, the answer is: It depends.

In fact, it depends mainly on the usecases where your class is used. Let's stick first to the example given in the question, the comparison of objects. Since it is not clearly visible from the question if we want to compare two phone objects or just a specific data member I will discuss both situations here.

Comparing a data member to out-of-class data

Let's take this usecase where we search for all phones with a weight bigger than x(just pseudocode):

for (Phone& p in phoneList) { if (p.getWeight() > x) { cout << "Found"; } }

Then the first class example is perfectly fine, since this is not an intrinsic feature of the phone, and thus the phone class is not responsible for handling it. In addition, the result does not expose more than absolutely required for the task.

Comparing two phone objects

In this case both code examples are equally good (or in this case equally bad). In both cases the user has to know a lot of details about how phones are represented to compare all necessary members. If in a later revision a new member is added to the class, every code segment that compares two phones has to be adapted. To overcome this, one can add a function to the class that does exactly the comparison.

class Phone { private: string producer, color; int weight, dimension; public: bool IsEqualTo(const Phone& other) { return (producer == other.producer && color == other.color &&....); }

Non comparitive usecase

But let's go to a more advanced example. Let's assume the following task: A user enters the pin to a phone and if it is the correct one, the phone should unlock. Let's assume a very naive approach:

class Phone { private: int pin; bool unlocked; public: int getPin() { return pin; } void unlock() { unlocked = true; } };

and the corresponding call

if (phone.getPin() == enteredPin) phone.unlock();

In this case we have a totally different situation. Here we need to consider the "tell, don't ask" rule, which basically says that it is a bad design to query the state of an object first, make a decision and then tell the object what to do. Instead we should only tell the object what we want, and let it do the work for us. In this usecase this is obvious, since unlocking the phone only when the pin is correct is a responsibility of the phone, not of the user that uses the phone class. But in more complex scenarious many programmers will do exactly what I described here.

Back to the problem: A good solution here would be for example

class Phone { private: int pin; bool unlocked; public: void CheckPin(int enteredPin) { if (pin == enteredPin) unlocked = true; } };

with the code

phone.CheckPin(enteredPin);

Hope this helps, and thanks to @KonradRudolph for pointing to the "tell, don't ask rule". Feel free to help me to improve the answer per commenting on it :)

更多推荐

const,void,private,string,电脑培训,计算机培训,IT培训"/> <meta name="des

本文发布于:2023-08-01 01:35:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1350497.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Prevent   breaking   encapsulation

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!