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

本文介绍了Ruby中的访问控制概念,包括public、private及protected的使用方式,并通过实例展示了如何利用这些关键字来控制方法的可见性。此外,还探讨了鸭子类型的概念,这是一种基于对象行为而非类型的多态思想。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

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

  1. public……以实例方法的形式向外部公开该方法
  2. private……在指定接收者的情况下不能调用该方法(只能使用缺省接收者的方式调用该方法, 因此无法从实例的外部访问)
  3. protected……在同一个类中时可将该方法作为实例方法调用
public 和 private 的例子:
class AccTest
def pub
puts "pub is a public method."
end
public :pub # 把pub 方法设定为public(可省略)
def priv
puts "priv is a private method."
end
private :priv # 把priv 方法设定为private
end
acc = AccTest.new
acc.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."
    end
end

Ruby protected 方法

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

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

class Point
attr_accessor :x, :y # 定义存取器
protected :x=, :y= # 把x= 与y= 设定为protected
def initialize(x=0.0, y=0.0)
@x, @y = x, y
end
def swap(other) # 交换x、 y 值的方法
tmp_x, tmp_y = @x, @y
@x, @y = other.x, other.y
other.x, other.y = tmp_x, tmp_y # 在同一个类中
# 可以被调用
return self
end
end
p0 = Point.new
p1 = 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.downcase
end
end
ary = ["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] 的形式,就被众多的类作为访问内部元素的手段而使用。刚开始时,我们可以先有意识地留意这种简单易懂的方法,然后再由浅入深,慢慢地就可以抓住窍门了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值