前言

上一篇我们简单介绍了下Ruby,这一节我们开始正式步入Ruby的世界,一探究竟。

Ruby特点

(1)面向对象支持。

(2)动态语言:我们可以修改已经定义过的类,也可以为现有类添加实例方法。

(3)可移植性好:不仅可以运行在UNIX操作系统上,还可以运行在Windows等操作系统上。

(4)弱类型语言:变量无需声明,变量没有类型,变量可以保存任何类型的数据。

(5)支持自动垃圾回收机制:避免我们手动进行垃圾回收。

(6)强大的异常处理机制:保证Ruby程序的健壮性。

(7)简洁的语法:提供正则表达式支持,并支持运算符重载。

(8)清晰的命名规则。

(9)动态载入:运行时取决于所运行的操作系统。

(10)完全免费。

Ruby程序注释

注释有两种形式:

(1)单行注释。

(2)多行注释。

Ruby使用井号(#)表示注释的开始,跟在#号后面直到#号在这行结束的代码将被解释器忽略。如下:

#定义一个方法
def method
puts "Hello World"
end

以上为单行注释。当然,我们有时需要为代码文档添加注释,这时我们可以用单行注释完成,此时文档代码注释就需要我们通过rdoc命令来提取注释。

Ruby命令规则

(1)以"$"开头的变量为全局变量。

(2)以“@”开头的变量为实例变量。

(3)以“@@”开头的变量为类变量。

(4)以小写字母或者下划线(_)开头的变量为局部变量。

(5)以大写字母开头的变量为常量。

常量

虽然Ruby只要求常量的首字母大写,但是为了提高可读性,一般我们建议对Ruby中的常量全部大写。

class Constant
# 定义一个常量
Foo = 5
# 重新赋值
Foo = 6
puts Foo
end

一般在其他编程语言中,对常量重新赋值,不会出错,但是在Ruby中,虽然不会抛出错误,但是会给出警告信息: warning: already initialized constant Constant::Foo

(1)对常量不能重新赋值

那么问题来了,常量是否可以定义在任何地方呢?我们看看

def info
FOO = 4
puts FOO
end

此时会抛出错误: dynamic constant assignment (SyntaxError)

(2)常量只能在类、模块里进行定义,绝不能在方法里定义。

Ruby变量及其作用域

局部变量

局部变量可以被定义在类内部、模块内部或者方法内部,当我们以一个小写字母开头的变量进行赋值时,就表明了一个局部变量。改变量的作用域仅仅属于该类、该模块或者该方法,一旦离开该类、该模块或方法,则此局部变量会自然消失。

# 定义一个类
class Apple
# 定义类里局部变量
local = "属于类的局部变量"
puts local
end # 定义一个方法
def info
# 定义方法里的局部变量
local = "属于方法的局部变量"
puts local
end # 调用方法
info # 定义一个模块
module Vegetable
# 定义模块里的局部变量
local = "属于模块里的局部变量"
puts local

上述分别在类、方法和模块里面定义了三个局部变量相同的名字,但是三个局部变量互不干扰,它们仅仅在它们对应的类、方法和模块内部有效。

【注意】我们可以定义一个顶层变量即未在上述类、方法以及模块内部,此时此顶层变量就在顶层对象中也就类似于C#中的Object对象中,此时该变量的作用域范围则是整个应用程序。

(1)局部变量不可在内部类和子类中访问。如下:

class Fruit
local = "Hello"
class Apple
puts local
end
end

此时会报错: undefined local variable or method `local' for Fruit::Apple:Class (NameError)

那么问题来了:要是我们在顶层对象中定义一个顶层变量,那么在类中是否能访问到呢?如下:

local = "Hello"
class Apple
puts local
end

此时同样也会报错,我们上述已经讲述,此顶层变量在顶层对象中,而此Apple则是顶层对象的子类,所以出现上述错误就解释的通了。

那么问题又来了:声明了局部变量后什么时候开始有效呢?我们来看看,测试便知:

class Apple
puts local
local = "Hello World"
end

此时报错如下:  undefined local variable or method `local' for Apple:Class (NameError)

当我们在类、模块和方法中声明局部变量时,此时该局部变量就开始生效,随着类、模块和方法的定义结束而结束,但是我们必须在定义之后再使用此局部变量才有效。

(2) 局部变量必须先定义,然后才可使用。

全局变量

由于全局变量可以在任何地方进行访问,所以通常我们应该尽量避免使用全局变量,因为全局变量会引起各个模块之间的耦合。如下

$global = "Hello World"
class Apple
puts $global
end def info
puts $global
end

我们定义了一个顶层的全局变量,该全局变量既可以在类中访问也可以在方法中访问。

(1)全局变量既可以在类中访问也可以在方法中访问。

那问题来了:全局变量是否必须和局部变量一样,先定义然后才能使用呢?我们看看:

class Apple
puts $global
end

一运行什么都没有也没出错,什么情况,我们再将代码修改如下:

class Apple
puts $global.nil?
end

最后打印为 true ,所以我们得出结论。

(2)全局变量无需变量声明,如果引用尚未初始化的全局变量,其值为nil。

实例变量

和静态语言不同,Ruby语言是一门动态语言,因为Ruby的实例变量无需声明,每个实例变量都会在第一次出现时动态加入对象。因此Ruby的实例变量通常在方法中定义类声明,即该实例变量是属于该方法所在类的实例,而不是该方法。我们来看看代码这句话说得到底是什么意思,实践出真知!

class Apple
# 定义第一个方法
def info1
# 输出实例变量@
puts @a
end
# 定义第二个方法
def info2
# 为实例变量赋值
@a = "Hello World"
end
end # 创建Apple类的实例
apple = Apple.new # 调用方法
apple.info2
apple.info1

即使我们在调用info1方法时此时实例变量@a并未定义,因为方法只有在真正调用时才生效,当我们调用info2方法时,此时会动态为Apple类添加一个@a的实例变量。

说明:在C#和Java中当创建对象时就会一次性为该对象的所有实例变量分配内存空间,但是Ruby却不是这样,因其动态性,在创建对象时该对象没有任何实例变量,直到执行到为实例变量定义时,该对象才动态增加该实例变量。同时它类似于全局变量,实例变量无需显示声明即可使用,若使用一个未定义的实例变量则该实例变量的值为nil。但是实例变量与局部变量还有一点区别就是在于其生命周期,实例变量的生命周期与其对象的生命周期是相同的,只要该类的对象存在,则该对象的实例变量则将一直存在;而局部变量则是随着方法的消亡而消亡(除非使用闭包)。

类变量

类变量从第一次开始赋值的地方开始生效,它既可以在类中定义,也可以在模块中定义,还可以在方法中定义。如下在类中定义类变量代码

class Apple
# 在类中定义一个类变量
@@color = "红色"
# 直接访问类变量
puts @@color
def info
# 在方法中访问类变量
puts "苹果的颜色是 "+@@color
end
end Apple.new.info

类变量和实例变量不同的是,类变量必须先定义,然后才能使用。若引用一个未定义的类变量,则会引发一个uninitialzed class varialbe。

同时我们也是可以在方法中定义类变量,如下:

class Apple
def color= (att)
# 定义类变量
@@color = att
end
def color
# 访问类变量
@@color
end
# 此处的@@color依然不可用
puts defined? @@color
end #创建两个Apple实例
a1 = Apple.new
a2 = Apple.new #依次为两个Apple的实例的@@color变量赋值
a1.color = "红色"
a2.color = "绿色"
#调用a1的方法来访问@@color变量
puts a1.color

上述打印出 绿色  ,当调用a1.color,此时@@color并未进行定义,此时@@color是为nil,然后将其类变量添加到该实例对象中,

那么问题来了:当调用a1.color = "红色"时,因为此前a2.color = "绿色",此时结果怎么会变成了“绿色”了呢?

此时则会涉及到类变量的一个特性:一个类 、其子类以及它们的实例的同名类变量共享了同一快内存区域即一个类、其子类以及它们的 实例的同名类变量都引用了同一个类变量。

结语

类变量与常量的区别

(1)类变量可以重复赋值(但对常量赋值会发出警告)。

(2)类变量默认是protected的,不能在类外部直接引用(在继承中可以引用或赋值)。

类变量与实例变量的区别

(1)在类范围内定义的类变量,可以在该类的方法中访问,但实例变量不行。

(2)类变量可在子类中引用或者赋值,但实例变量值可在类范围内直接引用或赋值。

Ruby之基础介绍(二)的更多相关文章

  1. python基础介绍二

    一.python种类 1.1 Cpython python官方版本,使用c语言实现,运行机制:先编译,py(源码文件)->pyc(字节码文件),最终执行时先将字节码转换成机器码,然后交给cpu执 ...

  2. Neo4J图库的基础介绍(二)-图库开发应用

    JAX-RS是一个用于构建REST资源的Java API,可以使用JAX-RS注解装饰每一个扩展类,从而让服务器处理对应的http请求,附加注解可以用来控制请求和响应的格式,http头和URI模板的格 ...

  3. Slickflow.NET 开源工作流引擎基础介绍(二) -- 引擎组件和业务模块的交互

    集成流程引擎的必要性 业务过程的变化是在BPM系统中常见的现象,企业管理层需要不断优化组织架构,改造业务流程,不可避免地带来了业务流程的变化,企业信息系统就会随之面临重构的可能性.一种直接的方式是改造 ...

  4. Slickflow.NET 开源工作流引擎基础介绍(二) -- 引擎组件和业务系统的集成

    集成流程引擎的必要性 业务过程的变化是在BPM系统中常见的现象,企业管理层需要不断优化组织架构,改造业务流程,不可避免地带来了业务流程的变化,企业信息系统就会随之面临重构的可能性.一种直接的方式是改造 ...

  5. Ruby语法基础(二)

    Ruby语法基础(二) 继续ruby的学习,这次主要把目光放到运算符,条件判断,循环,方法,以及其他ruby特有的基本概念上 运算符 算术运算符:+,-,/,%,**,值的注意的是,ruby中一切皆为 ...

  6. {Django基础十之Form和ModelForm组件}一 Form介绍 二 Form常用字段和插件 三 From所有内置字段 四 字段校验 五 Hook钩子方法 六 进阶补充 七 ModelForm

    Django基础十之Form和ModelForm组件 本节目录 一 Form介绍 二 Form常用字段和插件 三 From所有内置字段 四 字段校验 五 Hook钩子方法 六 进阶补充 七 Model ...

  7. { MySQL基础数据类型}一 介绍 二 数值类型 三 日期类型 四 字符串类型 五 枚举类型与集合类型

    MySQL基础数据类型 阅读目录 一 介绍 二 数值类型 三 日期类型 四 字符串类型 五 枚举类型与集合类型 一 介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己 ...

  8. XML基础介绍【二】

    XML基础介绍[二] 1.schema约束dtd语法: <!ELEMENT 元素名称 约束>schema符合xml的语法,xml语句.一个xml中可以有多个schema,多个schema使 ...

  9. php基础篇-二维数组排序 array_multisort

    原文:php基础篇-二维数组排序 array_multisort 对2维数组或者多维数组排序是常见的问题,在php中我们有个专门的多维数组排序函数,下面简单介绍下: array_multisort(a ...

随机推荐

  1. BZOJ4262: Sum

    Description   Input 第一行一个数 t,表示询问组数. 第一行一个数 t,表示询问组数. 接下来 t 行,每行四个数 l_1, r_1, l_2, r_2.   Output 一共 ...

  2. sublime下安装ctags

    sublime下安装ctags 标签: sublime   当我们阅读代码时, 会遇到很多不明确的函数名, 此时, 我们需要查看这个函数的定义的地方, 在sublime下我们需要安装一个插件, Cta ...

  3. BOM

    一.window对象1.全局作用域全局变量不能通过delete操作删除,而直接在window对象上定义的属性可以 var a = 1; delete a; console.log(a); window ...

  4. java反射技术详解

    反射: 其实就是动态的从内存加载一个指定的类,并获取该类中的所有的内容. 反射的好处:大大的增强了程序的扩展性. 反射的基本步骤: 1. 获得Class对象,就是获取到指定的名称的字节码文件对象. 2 ...

  5. Xamarin的不归路-生成安卓错误3

    错误提示: 解决方案:升级jdk到8即可. 2016年9月1日14:50

  6. backbone入门示例

    最近因为有个项目需要用backbone+mui  所以最近入坑backbone. Backbonejs有几个重要的概念,先介绍一下:Model,Collection,View,Router.其中Mod ...

  7. nginx超时重发

    最近一直遇到一个bug: 客户端会二次请求服务端,服务端多次调用remote服务. 特点是,这些请求都是模型切片相关的,耗时很长的请求,往往需要1分钟左右. 开始以为是客户端代码有问题,进行了二次请求 ...

  8. sql查询

    结果集是 id name 1 张三2 张三3 李四4 王五5 王五我想查询出有多少不重名的人的数量,并显示在每一行结果集里面结果如下:num id name 3     1   张三3     2  ...

  9. 关于Mathematica 的cdf 文件的嵌入应用

    // // '); cdf.embed('http://files.cnblogs.com/Leonhard-E/AreaOfANormalDistribution.cdf', 635, 913); ...

  10. maven 本地仓库和远程仓库

    在Maven中,任何一个依赖.插件或者项目构建的输出,都可以称之为构件. Maven在某个统一的位置存储所有项目的共享的构件,这个统一的位置,我们就称之为仓库.(仓库就是存放依赖和插件的地方) 任何的 ...