Ruby之基础介绍(二)

前言

上一篇我们简单介绍了下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)类变量可在子类中引用或者赋值,但实例变量值可在类范围内直接引用或赋值。

 

时间: 2024-10-13 11:09:31

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

BIOS是什么?最全BIOS基础介绍教程

本文主要为大家介绍一下BIOS相关的基础知识,包括BIOS基础介绍.BIOS中英文对照表(第2页).BIOS自检响铃含义(第3页).BIOS常见错误信息和解决方法(第4页).BIOS密码相关(第5页). 一.BIOS是什么? BIOS(basic input output system 即基本输入输出系统)是一组固化到计算机内主板上一个ROM芯片上的程序,它保存着计算机最重要的基本输入输出的程序.系统设置信息.开机后自检程序和系统自启动程序. 其主要功能是为计算机提供最底层的.最直接的硬件设置和

Ruby Fiber指南(二)参数传递

  Ruby Fiber指南(一)基础     Ruby Fiber指南(二)参数传递     Ruby Fiber指南(三)过滤器    Ruby Fiber指南(四)迭代器     Ruby Actor指南(五)实现Actor     这一篇其实也算是Fiber编程的基础篇,只不过参数传递算是一个比较重要的主题,因此独立一节.参数传递发生在两个Fiber之间,作为Fiber之间通讯的一个主要手段.     首先,我们可以通过resume调用给Fiber的block传递参数: 1 #resum

Lucene.Net 2.3.1开发介绍 —— 二、分词(四)

原文:Lucene.Net 2.3.1开发介绍 -- 二.分词(四) 2.1.2 可以使用的内置分词   简单的分词方式并不能满足需求.前文说过Lucene.Net内置分词中StandardAnalyzer分词还算比较实用(见1.1.2小节).StandardAnalyzer为什么能满足我们的部分需求,而它又有哪些不足呢?看分词的好坏还是要从效果说起.简单的说,在中英文混合的情况下,StandardAnalyzer会把英文按空格拆,而中文则按单字拆.因为中文是按单字拆,所以对分词的准确性起到了干

企业IT管理必备 数据库审计基础介绍

本文讲的是企业IT管理必备 数据库审计基础介绍,随着信息化的深入和普及,各行各业对信息系统的依赖性越来越强,信息系统中的数据也逐渐成为了企业的生命.数据的不准确.不真实.不一致.重复杂乱等就会影响企业的健康.于是数据审计登上了历史舞台,数据是由信息系统中的数据库进行生成.保存和管理. 一.几个概念 1.什么是审计:信息系统审计来源于传统的财务审计,因此审计是独立于被审计单位的机构和人员,对被审计单位的财政.财务收支及其有关的经济活动的真实.合法和效益进行检查.评价.公证的一种监督活动. 2.什么

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

原文:php基础篇-二维数组排序 array_multisort 对2维数组或者多维数组排序是常见的问题,在php中我们有个专门的多维数组排序函数,下面简单介绍下: array_multisort(array1,sorting order, sorting type,array2,array3..)是对多个数组或多维数组进行排序的函数. array1 必需.规定输入的数组. sorting order 可选.规定排列顺序.可能的值是 SORT_ASC 和 SORT_DESC. sorting t

Linux中BSD套接口开发的基础介绍_unix linux

    这是关于如何用各种可以得到的接口为Linux开发网络程序的系列文章的第一篇.就像大多数Unix-based的操作系统一样,Linux支持将TCP/IP作为本地的网络传输协议.在这个系列中,我们假定你已经比较熟悉Linux上的C编程和Linux的一些系统知识诸如signals,forking等等. 这篇文章是关于如何用BSD套接口创建网络程序的基础介绍 .在下一篇中,我们会解决涉及到建立(网络)deamon进程的问题.而且今后的文章我们还会涉及到使用远程过程调用(RPC),以及用CORBA

CAD新建绘图图层和定义颜色及线宽的基础介绍

  CAD新建绘图图层和定义颜色及线宽的基础介绍         我们在拿到cad图纸的时候,不管是建筑平面图还是结构图,都可以看到不同结构有着不同颜色,而且文字也能变成不同颜色.其实这是设计人员在不同图层修改了线段的特性,在话对应结构的是狗变换到对应图层就行.那么如何新建图层和修改特性呢.下面小编就来以2010cad为例介绍步骤(其他cad步骤也是一样,找到"图层",其他步骤一样的). 1.打开cad,点击如图所示图标"图层特性管理器" 2.或者点击界面栏中的&q

《Java特种兵》5.1 基础介绍

5.1 基础介绍 5.1.1 线程基础 本节内容介绍给那些还没接触过Java线程的朋友希望能有个感性认识. Java线程英文名是Thread所有的Java程序的运行都是在进程中分配线程来处理的.如果是一个main方法则由一个主线程来处理如果不创建自定义线程那么这个程序就是单线程的.如果是Web应用程序那么就由Web容器分配线程来处理在4.4.1节中介绍了在Tomcat源码中是如何分配线程的. 也许在使用main方法写代码时我们感觉不到多线程的存在在Web程序中也感觉不到多线程和自己编写程序有什么

XMOVE3.0手持终端——软件介绍(二):在2KB内存的单片机上实现的彩屏GUI控件库

一. 综述 嵌入式系统发展日新月异,安卓和ios已然战胜了当年雄霸天下的塞班,界面是我们特别看重的因素之一.不过你考虑过自己做一套系统,写一个界面库么?在单片机上自制系统,可以很好的锻炼编程能力和架构设计能力. 这些界面库都是在底层画点画线的驱动程序上实现的,基于我的XMOVE动作感应系统.基本具有硬件无关性.支持彩屏320*240的分辨率,由于考虑不同分辨率的开发过分复杂(想想看你需要计算每个点布局在哪个位置,这对安卓等系统都是大问题),因此我并没有太过完善的考虑过其他分辨率. 我已经写过一篇