Make interfaces easy to use correctly and hard to use incorrectly
接口,顾名思义,供别人使用的一些方法。function 接口,class接口,template 接口。。。。每一种接口都是客户与你的代码互动的手段。但是你所设计的接口的好坏,直接导致了被调用产生错误的几率。所以:“容易被正确使用,不容易被误用”的接口的重要性。 下面以书中表现日期的class 设计。
class myDate { public : myDate(int month,int day, int year); //... };
当调用这个日期类的时候,我们不知道三个参数各个代表了什么,比如
myDate md(14,3,2011);
这样的初始化,是完全错误的,因为没有14个月份。
所以我们要想办法杜绝这种现象的出现。
第一种方法就是导入简单的 wrapper types来区别天数,月份,和年。如
struct myDay { explicit myDay(int d) :val(d){} int val; }; struct myMonth { explicit myMonth(int d) :val(d){} int val; }; struct myYear { explicit myYear(int d) :val(d){} int val; }; 此时,我们的Date类就为 class myDate { public : myDate(const myMonth & m,const myDay &d,const myYear & y); //... };
这个时候,当我们初始化时,
myDate md(14,3,2011); ////会报错 myDate myD(myMonth(3),myDay(3),myYear(2011)); ////////正确
但是,因为一年只有十二个有效月份,所以,我们就预先定义好所有的月份。
struct myMonth { public: static myMonth jan(){return myMonth(1);} static myMonth Feb(){return myMonth(2);} static myMonth mar(){return myMonth(3);} //..... static myMonth Oct(){return myMonth(10);} ////.... };
当我们初始化时:
myDate myD(myMonth::Feb(),myDay(3),myYear(2011));
其他天数,和年份都可以这样。
预防客户出错调用就是利用限制类型表示什么可以做,什么不可以做。常见的就是const修饰。
避免无端与内置类型不兼容,真正的理由是为了提供行为一致的届接口。不一致性很容易导致接口的错误调用。
stl 容器届口十分的一致。每个容器都有名为size的成员函数,返回容器内有多少对象。但是java 就有length和size
很多方法。我之前做过一年的 java 深有体会。
在条款13中,我们学习到了factory函数,缠身一个对象的指针,方便我们对对象的管理,如
Investment* createInvestment();
在资源管理的那个章节,我们知道管理资源的重要性,我们要对指针删除,会出现
忘记删除,删除多次。
所以,我们使用了智能指针。让指针管理。std::tr1::shared_ptr<Investment.createInvestment();
shared_ptr的一个构造函数提供了技术功能,有如下代码:
std::tr1::shared_ptr<Investment> creatInvestment() { std::tr1::shared_ptr<Investment> retVal(static_cast<Investment*>(0),getRidOfInvestment); retVal=...; retrun retVal; } static_cast<Investment* >(0),强制转换为指针类型。
请记住:
■ 好的接口很容易被正确使用,不容易被误用.你应该在你的所有接口中努力达成这些性质.
■ "促进正确使用"的办法包括接口的一致性,以及与内置类型的行为兼容.
■ "阻止误用"的办法包括建立新类型、限制类型上的操作、束缚对象值以及消除客户的资源管理责任.
■ tr1::shared_ptr支持定制型删除器.这可防范DLL问题,可被用来自动解除互斥锁等等.
■ 好的接口很容易被正确使用,不容易被误用.你应该在你的所有接口中努力达成这些性质.
■ "促进正确使用"的办法包括接口的一致性,以及与内置类型的行为兼容.
■ "阻止误用"的办法包括建立新类型、限制类型上的操作、束缚对象值以及消除客户的资源管理责任.
■ tr1::shared_ptr支持定制型删除器.这可防范DLL问题,可被用来自动解除互斥锁等等.