Ruby学习笔记(21)_限制权限

来源:互联网 发布:帝国cms支付 编辑:程序博客网 时间:2024/05/22 00:48

即public, private, protected使用, Ruby 和 Java 完全不同, 需要新的理解.

到目前为止, 我们定义的方法, 都能作为实例方法被任意调用, 但是有时候我们可能并不希望这样。 例如, 只是为了汇总多个方法的共同处理而定义的方法, 一般不会公开给外部使用。

没有指定访问级别的方法默认为 public, 但 initialize 方法是个例外, 它通常会被定义为 private。

Ruby 提供了 3 种方法的访问级别, 我们可以按照需要来灵活调整。

  1. public……以实例方法的形式向外部公开该方法
  2. private……在指定接收者的情况下不能调用该方法(只能使用缺省接收者的方式调用该方法, 因此无法从实例的外部访问)
  3. protected……在同一个类中时可将该方法作为实例方法调用

public 和 private 的例子:

class AccTestdef pubputs "pub is a public method."endpublic :pub # 把pub 方法设定为public(可省略)def privputs "priv is a private method."endprivate :priv # 把priv 方法设定为privateendacc = AccTest.newacc.pub#acc.priv 这个调用会报错

AccTest 类的两个方法中, pub 方法可以正常调用, 但是在调用 priv 方法时程序会发生异常

批量定义多个方法访问级别

class AccTest    public # 不指定参数时,    # 以下的方法都被定义为public    def pub        puts "pub is a public method."    end    private # 以下的方法都被定义为private    def priv        puts "priv is a private method."    endend

Ruby protected 方法

在同一个类(及其子类) 中可作为实例方法使用, 而在除此以外的地方则无法使用

定义了拥有 X、 Y 坐标的 Point 类。 在这个类中, 实例中的坐标可以被外部读取, 但不能被修改。 为此, 我们可以利用 protected 来实现交换

class Pointattr_accessor :x, :y # 定义存取器protected :x=, :y= # 把x= 与y= 设定为protecteddef initialize(x=0.0, y=0.0)@x, @y = x, yenddef swap(other) # 交换x、 y 值的方法tmp_x, tmp_y = @x, @y@x, @y = other.x, other.yother.x, other.y = tmp_x, tmp_y # 在同一个类中# 可以被调用return selfendendp0 = Point.newp1 = Point.new(1.0, 2.0)p [ p0.x, p0.y ] #=> [0.0, 0.0]p [ p1.x, p1.y ] #=> [1.0, 2.0]p0.swap(p1)p [ p0.x, p0.y ] #=> [1.0, 2.0]p [ p1.x, p1.y ] #=> [0.0, 0.0]p0.x = 10.0 #=> 错误(NoMethodError)

鸭子类型

额….swap(other)这个参数是什么鬼?再查下资料更新吧, 对象作为方法参数时候写法可以这么任性?

上面对于方法传参没有限制参数类型的疑问, 阅读”ruby基础教程”解疑如下:
,我们来看一种结合对象特征,灵活运用多态的思考方法——鸭子类型(duck typing)。鸭子类型的说法来自于“能像鸭子那样走路,能像鸭子一样啼叫
的,那一定就是鸭子”这句话。这句话的意思是,对象的特征并不是由其种类(类及其继承关系)决定的,而是由对象本身具有什么样的行为(拥有什么方
法)决定的。例如,假设我们希望从字符串数组中取出元素,并将字母转换成小写后返回结果

def fetch_and_downcase(ary, index)if str = ary[index]return str.downcaseendendary = ["Boo", "Foo", "Woo"]p fetch_and_downcase(ary, 1) #=> "foo"

实际上,除了数组外,我们也可以像下面那样,把散列传给该方法处理。

hash = {0 => "Boo", 1 => "Foo", 2 => "Woo"}p fetch_and_downcase(hash, 1) #=> "foo"
fetch_and_downcase 方法对传进来的参数只有两个要求:
1.能以 ary[index] 形式获取元素
2.获取的元素可以执行 downcase 方法

只要参数符合这两个要求,fetch_and_downcase 方法并不关心传进来的到底是数组还是散列。

Ruby 中的变量没有限制类型,所以不会出现不是某个特定的类的对象,就不能给变量赋值的情况。因此,在程序开始运行之前,我们都无法知道变量指定的对象的方法调用是否正确。

这样的做法有个缺点,就是增加了程序运行前检查错误的难度。但是,从另外一个角度来看,则可以非常简单地使没有明确继承关系的对象之间的处理变得通用。只要能执行相同的操作,我们并不介意执行者是否一样;相反,虽然实际上是不同的执行者,但通过定义相同名称的方法,也可以实现处理通用化。

这就是鸭子类型思考问题的方法。
利用鸭子类型实现处理通用化,并不要求对象之间有明确的继承关系,因此,要想灵活运用,可能还需要花不少功夫。例如刚才介绍的 obj[index] 的形式,就被众多的类作为访问内部元素的手段而使用。刚开始时,我们可以先有意识地留意这种简单易懂的方法,然后再由浅入深,慢慢地就可以抓住窍门了。

原创粉丝点击