Your latest client is a bank, and they’ve tasked you with requiring customers to enter their password in order to make withdrawals.

Currently, this is what they’ve got:

class Customer
attr_reader :funds def initialize(funds, password)
@funds = funds
@password = password
end def remove_funds(amount)
@funds -= amount
end
end

Let’s break that apart. You can paste that whole class into irb to follow along.

When a customer is initialized, it receives a specified amount of funds and a password is set.

diego = Customer.new(500, "udacious")
# => #<Customer:0x007fcdb48ca5a8 @funds=500 @password="udacious">

Thanks to the attr_reader, you can see the value of his current funds.

diego.funds
# => 500

And the remove_funds method allows funds to be removed from the customer’s account.

Checking on the funds again confirms this.

diego.remove_funds(50)
# => 450
diego.funds
# => 450

These methods, funds and remove_funds, are part of the Customer class’ API, or application programming interface.

An API is, according to Wikipedia, “a set of routines, protocols, and tools for building software applications”.

Well, that’s vague.

“API” is a popular term in recent years, but many people use it without quite understanding what it means. Think of methods like remove_funds as your way of interfacing with the Customer class. These methods are the keys to accessing information about a particular customer.

There isn’t currently a way to access the @password instance variable.

It could be said that the customer’s password can’t be accessed by the customer’s public API.

In this situation, that’s a good thing! You don’t want information like a password to be publicly available to other objects.

Let’s implement a method called withdraw_securely, which takes two arguments, amount andpassword.

If the password entered matches the customer’s password, go ahead and remove the funds. Otherwise, nothing happens.

class Customer
attr_reader :funds def initialize(funds, password)
@password = password
@funds = funds
end def remove_funds(amount)
@funds -= amount
end def withdraw_securely(amount, password)
if password == @password
remove_funds(amount)
end
end
end

Play around with this in irb to see it in action.

diego.withdraw_securely(50, "udacious")
# => 400
diego.withdraw_securely(100, "wrong password")
# => nil
diego.funds
# => 400

✨Hooray. Calling withdraw_securely using the correct password decreases the total funds by calling remove_funds,

while using the incorrect password does nothing.

There’s one issue here, can you spot it?

diego.remove_funds(75)
# => 325
diego.funds
# => 325

Malicious users can still withdraw funds directly using the remove_funds method!

Public and Private Interfaces in ruby的更多相关文章

  1. Ruby中访问控制符public,private,protected区别总结

    重点关注private与protected public 默认即为public,全局都可以访问,这个不解释 private C++, “private” 意为 “private to this cla ...

  2. swift 中关于open ,public ,fileprivate,private ,internal,修饰的说明

    关于 swift 中的open ,public ,fileprivate,private, internal的区别 以下按照修饰关键字的访问约束范围 从约束的限定范围大到小的排序进行说明 open,p ...

  3. public protect private. 草稿。

    public protect private. 草稿. #include <iostream> #include <thread> #include <memory> ...

  4. Java修饰符public,private,protected及默认的区别

    Java中访问修饰符public.private.protecte.default的意义讲解:public(接口访问权限): Java语言中访问限制最宽的修饰符,一般称之为“公共的”.被其修饰的类.属 ...

  5. C++中public,protected,private派生类继承问题和访问权限问题

    C++中public,protected,private派生类继承问题和访问权限问题 当一个子类从父类继承时,父类的所有成员成为子类的成员,此时对父类成员的访问状态由继承时使用的继承限定符决定. 1. ...

  6. 【转载】C++中public,protected,private访问

    第一:private, public, protected 访问标号的访问范围. 假如我们约定: 类内部-----指的是当前类类型的定义中,以及其成员函数的声明和定义中: 类外部-----指的是不在当 ...

  7. JAVA修饰符类型(public,protected,private,friendly)

    转自:http://www.cnblogs.com/webapplee/p/3771708.html JAVA修饰符类型(public,protected,private,friendly) publ ...

  8. php public protected private属性实例详解

    php 类中函数和类变量都有三个属性:public protected private,具体什么时候使用什么属性好纠结,特意找了个实例,这样看起来更清晰. public 表示全局,类内部外部子类都可以 ...

  9. C# 访问控制:public、private、protected和internal

    平日工作时最常用的访问控制符是public和private,当看到prism里面大量使用protected的时候,觉得还是不太理解为啥. 所以就静下心来查找并理解了一下,这里记录下,以便回顾和交流. ...

随机推荐

  1. php检测php.ini是否配制正确

    运行命令行 php -d display_startup_errors=1 -d error_reporting=-1 -d display_errors -c "C:\path-to-ph ...

  2. Linq之Lambda表达式初步认识

    目录 写在前面 匿名方法 一个例子 Lambda 定义 一个例子 总结 参考文章 写在前面 元旦三天在家闲着无事,就看了看Linq的相关内容,也准备系统的学习一下,作为学习Linq的前奏,还是先得说说 ...

  3. python 逐行读取文件的三种方法

    方法一: 复制代码代码如下: f = open("foo.txt")             # 返回一个文件对象  line = f.readline()             ...

  4. 第九章:Java----泛型学习(最后过一遍)

    泛型:让集合记住里面元素的类型,避免取出时需要强制类型转换(大到小).   ClassCastException! 编译阶段就能发现错误.  语法更严格! 更不容易犯错! 1. 构造器的名字还是类名, ...

  5. java_WEB开发 防刷新

    客户端处理: 面对客户端我们可以使用Javascript脚本来解决,如下 1.重复刷新.重复提交 Ways One:设置一个变量,只允许提交一次. <script language=" ...

  6. iOS开发小技巧--高斯模糊框架的应用

    事件背景:彩票项目中点击检查更新之后的操作,高斯模糊效果并弹出HUD 注意:在应用别人的框架的时候,最好封装一下下. 新建一个类  继承自高斯模糊的类. 使用方法:新建一个高斯模糊类的View,添加到 ...

  7. hdu3986 spfa+枚举

    这题让我第一次感受到了什么叫做在绝望中A题.这题我总共交了18次,TLE不知道几次,WA也不知道几次. 这题不能用dijkstra,用这个我一直超时(我没试过dij+优先队列优化,好像优先队列优化后可 ...

  8. Oracle数据库语句大全

    转自:http://blog.sina.com.cn/s/blog_b5d14e2a0101c56z.html ORACLE支持五种类型的完整性约束 NOT NULL (非空)--防止NULL值进入指 ...

  9. Sqlserver 读取EXCEL

    1.1 启用本地读取设置 --启用EXEC sp_configure 'show advanced options', 1RECONFIGUREEXEC sp_configure 'Ad Hoc Di ...

  10. CCNET配置文件配置工具

    当我们在使用CruiseControl.NET进行配置的时候,你会发现配置文件是个非常头痛的事,无从下手,下面我在google找了一个09年的工具,主要是针对CruiseControl.NET进行配置 ...