先看一个类:
class Student{
public:
Student(){}
~Studnet(){}
int getAge() const;
void setAge(int _age);
...
private:
int age;
string gender;
...
};
这是一个用来表示学生的类,我们用一个int类型的值age
来表示student的年龄。假如有两个student,A和B,分别有 auto ageA =A.getAge()
和auto ageB = B.getAge()
。然后我们继续写代码,不知不觉的给用这两个做了好多的运算,如ageA+ageB
,ageA-ageB
或者ageA*ageB
。前两个对你来说还是有意义的,ageA+ageB
可以表示两个人的年龄和,ageA-ageB
可以表示A比B大多少,那么ageA*ageB
表示什么呢?这一定是使人费解的。因为,对于年龄来说,是没有乘法操作。我们会怀疑是不是写代码的人写错了呢。
为什么会这样呢?因为int所抽象的范围要比年龄大的多,int
不仅可以表示年龄,还有人数等其他的数量。使用int
来表示年龄,就给年龄添加了本不属于它的方法。我们需要给int
加一点点的限制:
class Age{
public:
Age(){age = 0;}
Age(int _age){
age = _age; //这里需要添加年龄上限的处理
}
~Age(){}
....
friend Age operator+(const Age& lhs, const Age& rhs){
return Age(lhs.age+rhs.age);
}
friend Age operator-(const Age& lhs, const Age& rhs){
return Age(lhs.age - rhs.age);
}
....
private:
int age;
};
class Student{
public:
Student(){}
~Studnet(){}
Age getAge() const;
void setAge(Age _age);
...
private:
Age age;
string gender;
...
};
这样如果再出现ageA*ageB
的情况,编译器就能检查出来了。
这其实是一种code smells,叫做Primitive Obsession。应该翻译为元类型的烂用。因为元类型,或者说是语言的内置类型抽象等级较高,能够表示的东西太多,自己本身的方法也比较多。当我们用圆类型来表示一种具体的类型的时候,要记得把我们不需要的方法给过滤掉,这样会减少很多令人困惑的问题。
网友评论