ruby 类方法 实例方法

本文探讨了Ruby语言中类方法与实例方法的区别及其使用方式。通过实例演示了如何定义和调用这两种方法,并解释了它们在Ruby内存模型中的位置。

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

 

 

刚刚接触Ruby不久,觉得Ruby也挺好玩的。
而在学的过程中,发现了Ruby中比较特别的地方:类方法和实例方法。
在Ruby中类方法和实例方法是有区别的,Ruby的类方法能被类对象调用,而实例方法就被实例对象调用。或许你已经想到,没错,类也是对象,这是Ruby和C++/Java的一个显著不同,在C++/Java中,类仅仅是一个数据抽象,并没有类也是对象这样的概念。而在Ruby中存在着元类的概念,类也是对象,所有类都是元类的实例对象。

 

Ruby的的实例方法和Java等其他语言的定义类似,直接用

class className
  ...
  def instance_methodName(args)
  end 
end

 或者用类外定义(和这个类似)

 class className
  ...
 end

 class className
  def another_instance_methodName(args)
  end
 end
 

 定义实例方法。

 

而类方法的定义,就在方法前加入类名称或者self关键字

class className
  ...
  def self.class_methodName(args)
  end 
end

 或者用类外定义

 class className
  ...
 end

 class<<ClaFun
  def self.another_class_methodName(args)
  end
 end

 定义类方法。

 

下面是例子,我们先定义一个Person类,然后就定义了一个实例方法talk方法和一个sleep的类方法

class Person
  def initialize(name,age=18)
  end
 
 def talk
     print("this is instance method talk")
  end

  def self.sleep
     print("this is class method sleep")
  end

end

 他们的调用方式就如下了

Preson.sleep  #调用self.sleep方法 输出"this is class method sleep"
aPerson=Person.new
aPerson.talk  #调用talk方法 输出"this is instance method talk"
#aPerson.sleep #报错

 从他们两的定义方法的形式可以看出,虽然他们的都是写在一个类里面,习惯了C++/Java的就容易认为他们的级别是相同的(都属于className下)。其实不然,他们并不是在同一个“类”中,前者在Class类的实例中,而后者在className类的实例中。就本例而言,self.sleep是一个类方法,而talk是一个实例方法。对一个特定对象来说,每个对象都会有一个talk方法的一份拷贝,他们是相互隔离互不影响的;而类方法则是所有类成员可以共享操作的方法。
这个证明过程很简单:

puts Person.methods
puts
puts aPerson.methods #和Person.instance_methods等同 

 就会发现sleep方法在Person.methods里面,而talk就在aPerson.methods里面。

那如果在类方法里买呢调用实例方法,或者在实例方法调用类方法呢?
根据刚才的理论,就可以如下调用

 

类方法里买呢调用实例方法用 self.new.instance_methodName(args)

def self.sleep
    self.new.talk #实例化一个对象再调用
    print("this is class method sleep \n")
end

 实例方法调用类方法则用 self.class.class_methodName(args)

def talk
   self.class.sleep #寻找类的方法
   print("this is instance method talk \n")
end

 而从另一个角度“存取控制”去看这个问题的话,类方法就相当于className类对象的私有的方法,实例对象不能直接调用,证明这在刚才调用aPerson.sleep的时候就知道了

aPerson.sleep #报错 private method `sleep' called for #<Person:0xb77075e4> (NoMethodError)

 所以在在className里面把类方法声明为Public,类的实例对象就可以直接调用了(就看在实际应用中有没有必要这样做了)

class className
  ...
  public :sleep
end
aPerson.sleep #没有报错,并且在aPerson.methods里也确实出现了sleep方法,但是貌似方法里面的代码没有执行,在这里就是没有输出,一个奇怪的地方。

 

 

个人觉得这种机制和JS的prototype是有相似之处的,但不是完全相似。

 

 

阐述就到这里吧,第一次发文章…………呵呵~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值