调用内置类实例对象的方法时如何工作?是否含实例变量?
我理解类就像创建对象的模具,类里定义了方法和各种变量(类变量、实例变量、局部变量等)。
比如下面这个自定义的Person类:
class Person def initialize (name,age) @name = name @age = age end def greeting "#{@name} says hi to you!" end end me = Person.new "John", 34 puts me.greeting
调用Person.new时,会创建Person类的对象,同时初始化对象的内部属性,这些属性存在实例变量@name和@age里,变量me就是这个新对象的引用。调用me.greeting时,会对me指向的对象调用greeting方法,这个方法会使用和该对象绑定的实例变量@name。所以调用对象方法本质是和对象交互,读取它存在实例变量里的属性,这部分我已经搞懂了。
现在我有个问题:用字符串字面量创建内置类(比如String、Array、Integer)的对象时,比如string = "hello",创建过程中会不会给这个对象存储一些信息到实例变量里?
我疑惑的点是string.upcase这类操作的原理:#upcase方法是怎么作用于string的?我猜测要返回大写字符串,这个字符串对象肯定绑定了某些实例变量,实例方法就是基于这些变量工作的?
解答
答案是肯定的,Ruby的内置类对象确实会在创建时存储核心数据到内部结构中,只不过这些数据不是我们自定义类里那种用@xxx声明的Ruby层面实例变量——因为Ruby的核心类大多是用C实现的,这些核心数据藏在底层的C结构体里,不会直接暴露给Ruby代码。
拿String对象来说:当你写出"hello"时,这个字符串对象的底层会存着字符内容、字符串长度、编码类型这些关键信息。upcase方法就是读取这些底层的字符数据,把小写字母转成大写,最后返回一个新的String对象(别忘了Ruby里字符串是不可变的,upcase不会改动原对象)。
你可以自己用instance_variables方法验证:自定义的Person对象调用me.instance_variables会返回[:@name, :@age],但"hello".instance_variables返回的是空数组——这就说明底层的核心数据没暴露成Ruby可见的实例变量,但像upcase、length这类实例方法,是能通过底层接口读取这些数据来工作的。
本质上,内置类和你写的自定义类逻辑是一致的:方法都依赖对象内部存储的数据,只是内置类把核心数据封装得更隐蔽,不让Ruby代码直接碰而已。
内容的提问来源于stack exchange,提问作者Lorenzo Zabot

