条款18:让接口容易被正确使用,不易被误用

简介: 条款18:让接口容易被正确使用,不易被误用
程序设计中经常遇到的便是如何设计接口,让用户能够直观的、快速的了解并上手使用接口。让接口容易被正确使用,不易被误用便是本条款所强调的。
理想上,如果客户企图使用某个接口而却没有获得他所预期的行为,这个代码不应该通过编译;如果代码通过了编译,他的作为就该是客户所想要的。

比如这样一个表示时间的类:

class Date {
public:
    Date(int month, int day, int year);
};

如果我们不对接口做一些“强制性“的约束,该接口就可能被误用:

Date date(2022, 2, 25); //传参顺序不对
Date date(31, -1, 0); //参数非法

虽然上述调用可以通过编译,但却可能与用户意图违背。为此我们可以采用类型系统:

class Month {
public:
    explicit Month(int m) : month(m) {
    }
private:
    int month;
};
class Day {
public:
    explicit Day(int d) : day(d) {
    }
private:
    int day;
};
class Year {
public:
    explicit Year(int y) : year(y) {
    }
private:
    int year;
};
class Date {
public:
    Date(const Month &m, const Day &d, const Year &y);
};

这时,我们对用户使用该类的方式做了一些约束,比如:

Date date(2022, 2, 25);       //报错,explicit禁止隐式类型转换
Date date(Day(25), Month(2), Year(2022));//报错,传参顺序不对
Date date(Month(2), Day(25), Year(2022));//正确

虽然我们对传参的顺序,方式做了一定的约束,但是还是避免不了传入非法值,比如:

Date date(Month(22), Day(25), Year(2022));

月份为22显然不合法。为此,我们可以预先定义所有有效的值(即告知用户,只能使用这几个值哦):

class Month {
public:
    static Month Jan() { return Month(1); }
    static Month Feb() { return Month(2); }
    //...
private:
    explicit Month(int m);
};

再使用时,只能这样,这样总不会写错了吧?:

Date date(Month::Jan(), Day(25), Year(2022));

预防用户错误的另一个做法是,限制类型内什么事可做,什么事不可做。常见的限制是加上const。

比如:我们重载了*并且返回值被const限定,当用户一不小心将==写成=时,程序可以告知用户,唉?你这里是不是要做比较?而不是赋值??

if (a * b = c) // ?

后面部分理解不是很透彻,再续。

关于shared_ptr删除器的使用:

void del(int *p) {
  cout << "del" << endl;
}
void func() {
  shared_ptr<int> p(new int(3), del);
  cout << p << endl;
  shared_ptr<int> p1(new int(4), [](int *p) { cout << p << endl; cout << "lambda" << endl; });
  cout << p1 << endl;
}
相关文章
|
5天前
|
Arthas SQL Java
不规范的枚举类代码引发的一场事故
作者参与了一个问题排查,最后得到的结论和枚举类的规范有关系,本文将过程总结在这里提供大家一起学习交流。
459 0
|
11月前
|
关系型数据库 MySQL API
被无视的小细节
被无视的小细节
52 0
|
监控 安全 数据安全/隐私保护
在开源代码的时候该如何避免安全风险的发生?
作为开发者来讲,不管是在实际开发中使用开源项目,还是直接投身于开源的贡献中,关于开源相关的内容想必都有自己独到的见解。开源与开发者息息相关,可能有的开发者会觉得不使用开源项目,自己就与开源无关了?这种想法是片面的,因为就算没有在实际开发中使用开源项目,但是在实际开发中肯定会用到一些第三方的插件,那么能保证这些插件没有用到开源的内容么?所以,开源与每一位开发者都有联系。
214 2
在开源代码的时候该如何避免安全风险的发生?
|
Java Maven
你有没有掉进去过这些 抽象类 和 接口 的 “陷阱“
你有没有掉进去过这些 抽象类 和 接口 的 “陷阱“
你有没有掉进去过这些 抽象类 和 接口 的 “陷阱“
|
设计模式 Java 程序员
怎样才能写出规范的好代码?
最近发现一件事情,自己写的代码和公司里工作5到10年的前辈写的代码虽然功能一样,但是他们的代码更规范,更优雅。比如有时候我会给一个需求写一个方法,但是有些人就可以好几个需求通过同一个方法实现。因此有了今天这个疑问,怎样才能写出规范的好代码?
|
Java 程序员
用了这么久的equals,你知道还要遵守约定么(上)
重写equals 方法看起来很简单,但是还会有多种方式导致出错,后果可能是严重的。最简单,最容易避免出错的方式是 避免重写equals方法 ,采用这种方式的每个类只需要和自己对比即可,这样永远不会出错。如果满足了以下任何一个约定,也能产生正确的结果:
用了这么久的equals,你知道还要遵守约定么(下)
重写equals 方法看起来很简单,但是还会有多种方式导致出错,后果可能是严重的。最简单,最容易避免出错的方式是 避免重写equals方法 ,采用这种方式的每个类只需要和自己对比即可,这样永远不会出错。如果满足了以下任何一个约定,也能产生正确的结果:
|
数据采集 前端开发 安全
网安入门须知:注释的危害居然这么大?——注释漏洞导致的信息泄露
注释导致的信息泄露 一、什么是信息泄露漏洞? 二、信息泄露有什么危害?
508 0
网安入门须知:注释的危害居然这么大?——注释漏洞导致的信息泄露
泛型带你规避风险 | 带你学《Java面向对象编程》之六十四
本节由转型风险引出了一个新的概念-泛型,并为读者简单介绍了泛型的定义方法与泛型类实例化方法。
|
JavaScript 程序员 PHP
注释里的诅咒:哪种语言遭受最多的咒骂?
导读:原文作者Scott Gilbertson在webmonkey.com发表一篇《Cussing in Commits: Which Programming Language Inspires the Most Swearing?》,由外刊IT评论整理翻译《注释里的诅咒:哪种语言遭受最多的咒骂?》。
951 0