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
51单片机学习笔记 2.zip
STM32学习笔记 2.zip
新版本笔记 2.xmind
2022.03.30 Python笔记2
SAPSD模块自学笔记2.doc
【光学】 光学笔记2.pdf
SSH学习笔记 SSH学习笔记 SSH学习笔记 SSH学习笔记 SSH学习笔记 SSH学习笔记 SSH学习笔记 SSH学习笔记 SSH学习笔记 SSH学习笔记 SSH学习笔记 SSH学习笔记