1. Classes and Modules
classes
and objects are both the highest-level constructs(构造) in Ruby and the
essential underpinnings(支柱 支撑) of the entire language
成语言的基础,使用语言的最高一级单位。
A. 基本定义方式
class Song
def initialize(name, artist, duration)
@name = name
@artist = artist
@duration = duration
end
end
initialize
是调用new时,分配uninitialized的对象内存后,会呼叫的一个函数,并传入new中的参数。
@
开头的变量是实例变量,属于object
Class variable以"@@
"
开头。在使用前必须被初始化(通常在class的定义中使用一条赋值语句)。
访问Class variable可以是实例的method,也可以是class method。
new是class method,而initialize是instance method。
- In
Ruby, classes are very open
and object state is rather close
。
- 在class内而在instance method外时,self指向当前class(即当前定在定义的class是当前的object).
在instance method内饰,self指向该class的一个实例。
- 4种定义class method的形式,两种是利用self替换class的名字
- private method不能指定reciever,只能在instance method(包括子类)中被调用,只有让self默默接收。
而protected则能在class或者subclass范围内指定某个reciever
- private_class_method :new 可把一个class_method私有化
- send 和instance_eval不受private的影响
B. Inheritance and Messages(继承和调用)
"< Song
"
说明Song是superclass, 但子类一般更好或更特别。
ruby的多态类似java,method调用时,先从子类找可以接受消息的method。
直接访问祖先的成员变量是一个不好的行为。
用method chaining 实现decorator模式,比如super.
C. Objects and Attributes
成员变量的访问通过定义method实现,定义与成员变量名称相同的method获取值,而变量名结尾跟着=
实现
写入method。rails自动完成这些attributes的method的添加。
angels on a pinhead 是指说不清道不明的问题,可以思辩但实际用时无所谓。
initialize只有一种,如果有多种构造方式,可以通过实现各factory并最终转化到initialize所需要的格式。
ruby内建的Singleton module实现了Singleton模式,主要完成了两件事情:
- private化诸如new之类的方法
- 创建一个class_method instance,所有的该类的实例都通过instance方法来创建
G. Constants
1. 定义在某个module或者class之内的constant,在内部使用时可以什么都不加,在其他地方使用时给出::并带有对应module或class的名称。
2.不定义在任何module或者class之内的变量,可直接使用,前面不用加任何东西。实际上该const属于Object.
4. Containers and Block
A. containers: objects that hold references to one or more other objects.
class SongList
def [](index)
@songs[index]
end
end
B. Block 的进一步说明
yield
中的参数
参数可以传多个,而且block中的参数和method中的参数是共享一个内存空间。
yield也可以返回值。
*args
, meaning “collect the actual parameters passed to the method into an array named args.” 传给其他函数时,也是按照*args的形式传入。
可变长度的参数列表(bundled into a new array)
block_given?
可以判断调用该method时,有没有传入block,以此可以给method制定不同的行为。
如File.open,在判断有block输入时,会执行block并在结束后close文件,如无block输入则简单的打开文件并返回文件引用。该函数位于Kernel类中。
C. Proc实例(将block变成变量保存下来)
method中最后的一个以&
开开头的参数表明调用该函数时,ruby必须要查找block。block会变成Proc的一个实例,之后可以使用。
def initialize(label, &action)
super(label)
@action = action
end
@action.call(self)
通过call传入的参数可以自己来掌握,并且即使该参数在上下文环境已经不存在时,能够继续使用。称做closure(it remembers the context in which it was defined, and it uses that context whenever it is called)
.
block内可以在之前环境已经消失的情况下,继续使用原始环境中的信息,只要在block中有这个变量存在过。
lambda
{|n| thing * n} 返回一个Proc 实例。thing可以在首次调用后一直保存。
1 通过&
传一个block
2 调用Proc.new
3 调用Kernel.lambda
前2个是raw procs
,后一个更像free-standing method body
.前两个得到的返回受block内部的return
影响,lambda则得到独立的代码块。
next
跳出该block并返回,对raw procs来说,break
跳出调用该block的method,都有返回值。
Containers, blocks, and iterators are core concepts in Ruby.
6. More on Methods
A. 定义method
method name小写开头,不然ruby会解析成常量
? ! =
是method 名字仅允许的几个不平凡的结尾
分别表示query, modify self(dangerous), assigmn.
参数名字也是小写,default value
可通过定义method时用赋值号=
给与。
method的body中还能继续定义method。method内是Ruby expressions。
*
开头的参数,表示不定长参数
&
开头的参数,会获得一个block
B. call
4要素:reciever
(object, self, class or module),method name
,参数
, block
如果返回多个参数,就会以array的形式返回。
在调用时,*
开头的参数,起到了expanding的作用(定义是bundled)
在调用时,&
开头的参数,ruby认为这是一个Proc实例,proc实例可通过lambda
方法获取。
calc = lambda {|n| n*number}
(1..10).collect(&calc).join(", ")
C. 传入hash (收集参数)
ruby不支持keyword arguments
的特性,而是使用hash来达到同样的效果。
ruby会自动把以 key=>value对收集
成一个hash并且作为一个参数传递
给method,只要这些pair跟随在普通参数后面、在*
和block
参数前面
。
Well-written: contain many methods, each quite small.
9. Modules
grouping together methods, classes, and constants.
1. provide a namespace
2. mixin facilty
.
A. Namespace
Modules定义了namespace,隔开了中间的methods和constants。
module Trig
PI = 3.141592654
def Trig.sin(x)
# ..
end
end
使用时,require
'trig'
,require后面跟随的是小写的文件名
。然后的调用方法与调用class method如出一辙。
method前面加.
,常量前加::
.
B. Mixin
在module
中定义实例method
,这些method不能被module的对象使用,因为module不能实例化对象。
但是,class可以include module,在这之后,所有的module中的实例method都会混入
class中。因此叫做
mixin。
include
后面跟随的是大写的module
名。require要在include前被使用
。多个class include的module指向同一个地址,所以如果在某个class中改变了module的一个行为,那么将影响全部相关的class
,这点在运行时也是如此。
mixin中的method和class的method协作
起来,将是很具有威力的。其实可以理解成module定义一个钩子,include module后class负责实现这个钩子,然后module中的method使用这个钩子来完成很多例行函数,在混合后,这些函数的意义就跟着class走了。如枚举模块,如比较大小模块
module中的实例变量名可能会与class中有冲突。一般来说module自己没有状态,或者保证名字不会冲突。
method重载时,先本class,其次mixin,再次是superclass
和superclass的mixin。最后一个include的module被优先搜索。
C. 自动更新
load
在每次method中都会被执行,require
只load一次某个给定的文件。
所以可以用load来动态刷新自己,这是动态语言的一大好处,不必重启服务、不必重新定义新的版本。
require 使得可以使用文件中的内容,include则使得module中的方法变成了实例方法。
分享到:
相关推荐
JAVAEE系列笔记2JAVAEE系列笔记2JAVAEE系列笔记2JAVAEE系列笔记2JAVAEE系列笔记2JAVAEE系列笔记2JAVAEE系列笔记2
20240126xml 笔记 2
java学习笔记2(多线程)java学习笔记2(多线程)
世界500强CFO的财务管理笔记2.epub世界500强CFO的财务管理笔记2.epub世界500强CFO的财务管理笔记2.epub世界500强CFO的财务管理笔记2.epub世界500强CFO的财务管理笔记2.epub
Python学习笔记--笔记2
成电考研通信原理笔记2成电考研通信原理笔记2
笔记2.zip
FreeRTOS学习笔记 2.zip
node笔记 2.zip
网工复习笔记2.rar 网工复习笔记2.rar
android开发笔记2,分享资料,希望对您的学习有所帮助。
尚硅谷电商项目笔记2
尚硅谷后台管理系统笔记2
这是我的Linux笔记2
51单片机学习笔记 2.zip
STM32学习笔记 2.zip
新版本笔记 2.xmind
2022.03.30 Python笔记2
SAPSD模块自学笔记2.doc
【光学】 光学笔记2.pdf