侧边栏壁纸
  • 累计撰写 218 篇文章
  • 累计创建 59 个标签
  • 累计收到 5 条评论

Ruby 基本语法笔记

barwe
2021-07-14 / 0 评论 / 0 点赞 / 770 阅读 / 4,117 字
温馨提示:
本文最后更新于 2022-07-18,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

puts 打印内容,带换行符

puts "Hello, Ruby!"

print 打印内容,不带换行符

多行字符串

>>>EOF
	这是第一种方式创建here document 。
    多行字符串。
EOF

BEGIN & END

BEGIN 声明的语句块会在程序运行之前被调用:

BEGIN {
    ...
}

END 声明的语句块会在程序结尾被调用:

END {
	...    
}

注释

单行注释:#

多行注释(嵌入式文档注释):

=begin
...
...
=end

数据类型

基本数据类型:

  • true.class => TrueClass
  • false.class => FalseClass
  • nil.class => NilClass
  • 1.class => Integer
  • 1.0.class => Float
  • 'a'.class => String
  • :a.class => Symbol

两种基本的数据结构:

  • [].class => Array
  • {}.class => Hash

一种特殊的数据结构:

  • (0..1).class => Range
  • (0...1).class => Range

整数

整数按照大小分为两种:

  • 四字节大小(-230 ~ 230-1)的为 Fixnum
  • 超过四字节的为 Bignum

添加不同的前导标志字符,以使用不同的进制:

  • 0 八进制
  • 0x 十六进制
  • 0b 二进制

获取字符的ASCII编码:

  • "a".ord => 97
  • "\n".ord => 92

将一个整数转换为ASCII字符:

  • 97.chr => "a"
  • 超出ASCII范围时抛出 RangeError

在一个表示整数的表达中(不论进制),可以使用下划线来分隔数字:

  • 十进制:123_456, 1_2_3_4
  • 八进制:0_1_2, 01_2
  • 十六进制:0x1_2_3, 但是 0x_123 不合法,下划线必须跟在数字后面,而且不能破坏 进制前导符
  • 比较常见的做法是使用下划线作为 千分符,如 1_000_000

浮点数

常见形式:

  • 3.14
  • 1E3 or 1e3 or 1E+3 or 1e-3
  • 1E-3 or 1e-3
  • 1.0e3

算术操作

除法 / 的结果类型取决于操作数的类型:

  • 整数除以整数返回整数
  • 至少一个为浮点数时返回浮点数

指数操作符:

  • 16**(1/4) => 1
  • 16**(1/4.0) => 2

字符串

双引号字符串 支持完整的转义序列,单引号字符串 只支持转义斜线本身和单引号。

单引号字符串('...')等价于 %q{...},双引号字符串等价于 %Q{...};定界符可以使用各种奇怪的字符。

构造

  • "aaa"
  • String "aaa" or String("aaa")
  • String.new "aaa" or String.new("aaa")

格式化

模板字符串:"#{EXPR}",只在双引号字符串中生效:

  • "#{1+1}" => "2"
  • '#{1+1}' => '#{1+1}'

% 格式化:

  • "%s" % 3 => "3"
  • "%s+%s" % [1, 1] => "1+1"
  • 由于 Ruby 没有 tuple,因此多个参数要用 [] 包裹

数组

哈希

创建

Ruby 实现的哈希集成了 Python 原生字典(Dict)和默认字典(collections.defaultdict)的功能。

创建一个默认值为 nil 的哈希:

d = {}
d = Hash.new

创建一个带默认值的哈希:

d = Hash.new 0

如果默认值是数组或者哈希,任何未定义键的查询都将返回默认对象的引用:

d = Hash.new []
d[:a] << :a
d[:b] #=> [:a]

在 Ruby 中,任何对象都可以作为键,包括数组、哈希。

d = Hash.new
x = [1, 2, 3]
y = [1, 2, 3]
x == y #=> true
x.object_id == y.object_id #=> false
d[x] = 1
d[y] #=> 1

从已知的键值对创建哈希:

d = Hash[1=>2,3=>4] # 1 #
d = {1 => 2, 3 => 4} # 2 #
{1: 2, 3: 4} # wrong
d #=> {1=>2, 3=>4}

增加

d[k] = v

删除

移除所有键值对

d.clear

查询

d[k]
d.default # 查询默认值

修改

d[k] = v

比较

## 比较两个哈希的字面值,所有键值对完全匹配
d1 == d2

判空方法

Ruby 中常见的对象判空方法有 .nil?, .empty?, .any?, .blank?, .present?

nil

相当于 Python 中的 None

nil 表示对象不存在,例如使用越界索引访问数组或者哈希的值会返回 nil

使用 .nil? 判断一个对象是否是 nil,除了 nil.nil?true 外,其他所有对象的 .nil? 均为 false

在条件判断中,nilfalse 相当。

empty & any

判断对象是否为空值,例如空字符串、空数组、空哈希等等:

"".empty? #=> true
[].empty? #=> true
{}.empty? #=> true

empty 判断的实际上是可迭代对象是否有可迭代元素,因此 niltrue, false 以及数值类型的对象没有 empty 方法。

注意区分 空字符串"")和 包含空白字符的字符串" ")。

any 方法用来判断 数组 或者 哈希 是否有元素,非空返回 true

[].any? #=> false
{}.any? #=> false
[1,2,3].any? #=> true
{"a": 97}.any? #=> true

String类型 的对象没有实现 .any? 方法=。

blank & present

使用这两个方法前需要先引入:

require 'active_support/core_ext'

blank 是一种相对于 empty 更加宽松的判空方法,真值范围包括:

  1. 对象为 nil,即 obj.nil? => true
  2. 对象为空,即 obj.empty? => true
  3. 特别的,空白字符串也会被检测为真值:" ".blank? => true

与 blank 相对的是 present 方法,它与 blank 完全相反。

presence

使用这个方法前需要先引入:

require 'active_support/core_ext'

presence 是三元运算符的一种简化形式,以下三种方式返回值相同:

obj.presence
obj.present? ? obj : nil
obj if obj.present?

当对象的 .present? 为真时返回对象本身,否则返回 nil

模块 Module

定义 module

Python 会将每个文件识别为一个模块,Ruby 需要用语法规定模块的范围:

module MODULE_NAME
    # 模块常量
    PI = 3.141592654
    # 模块方法
    def MODULE_NAME.METHOD_NAME()
        #...
    end
end

调用 module

# 调用模块常量
MODULE_NAME::PI #=> 3.141592654
# 调用模块方法
MODULE_NAME.METHOD_NAME()

引入 module

## 1 ##
$LOAD_PATH << '.' # 在当前目录中搜索模块
require 'FILE_NAME.rb' # 从当前目录下的文件中导入模块
require 'FILE_NAME' # 从当前目录下的文件中导入模块

## 2 ##
require_relative 'FILE_PATH' # 从相对路径中导入

Mixin

Ruby 的类不支持多重继承,其多重继承借助于模块的 Mixin 机制实现。

将模块 include 到类定义中,模块中的方法就 mix 进了类中。

在类中嵌入模块:

class CLASS_NAME
    include MODULE_NAME_1
    include MODULE_NAME_2
    #...
end

类通过 include 多个模块实现了 Mixin 机制,从而近似等价实现了多继承。

定义在模块 MODULE_NAME_1 和 MODULE_NAME_2 中的方法可以被类直接调用。

else

判断对象是否已经存入数据库

将数据存入数据库的过程也是一个 数据持久化(persist)的过程。

构造一个新对象:

obj = Obj.new
obj.persisted? #=> false
obj.new_record? #=> true

将对象持久化:

obj.save
obj.persisted? #=> true
obj.new_record? #=> false

查看类的接口

获取某个类的直接父类:

SomeClass.superclass
# Array.superclass => Object

获取某个类的所有祖宗类:

SomeClass.ancestors
# Array.ancestors =>
# [ActiveSupport::ToJsonWithActiveSupportEncoder, Array, JSON::Ext::Generator::GeneratorMethods::Array, ActiveSupport::ToJsonWithActiveSupportEncoder, Enumerable, ActiveSupport::ToJsonWithActiveSupportEncoder, Object, JSON::Ext::Generator::GeneratorMethods::Object, ActiveSupport::Tryable, Kernel, BasicObject]

查看某各类实现了哪些方法:

SomeClass.methods

查看某各类是否实现了某个方法:

SomeClass.response_to? :METHOD_NAME
# Array.response_to? :new => true
0

评论区