欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Ruby入坑指南

程序员文章站 2022-03-02 08:12:41
Ruby语言是由*(Matz)设计,是一门通用的、面向对象的、解释型语言。 ......

1.1 简介

ruby语言是由*(matz)设计,是一门通用的、面向对象的、解释型语言。

1.2 ruby?ruby?ruby?

1.ruby:用来表示编程的语言
2.ruby:是指一个计算机程序,特指ruby的解释器
3.ruby:准确来说没有这种写法,一般是简写,例如wto.

1.3. 安装方式

方式1 brew

brew install ruby

方式2 rvm

rvm install 2.2.4

更多rvm可以参考:

1.4 工具

1.irb:交互式ruby控制台程序。

2.: ruby version manager

3.vscode

4.gem:一套ruby库和应用程序包管理实用工具

5.rake:ruby的make工具,一套任务管理实用工具

6.rdoc和ri:ruby文档工具

1.5 ruby解释器命令

执行ruby文件

ruby basic.rb

语法检查而不运行程序:

ruby -cw basic.rb

它会读取文件并指出语法是否有错。更多类似-cw的解释器开关参见文末:解释器的命令行开关。

2 ruby语言基础

2.1 变量

局部变量

局部变量以小写字母或者下划线开头,包含字母、下划线或数字。ruby不是使用的驼峰命名,而是使用下划线将多个单词拼接。例如:

✅first_name 
❎firstname 

实例变量

实例变量通常以一个单独的@开头,后面字符和局部变量命名规则一致。例如:

class person
    def initialize(temp_name,temp_age)
        @name = temp_name
    end
    def printn
        return @name
    end
end
# 实例变量
p1 = person.new("zhangsan",24)
p p1.printn
#输出结果为:zhangsan

类变量

类变量命名规则与实例变量一致,但是它以@@符号开头:

class person
    @@person_number = 0
    def initialize(temp_name,temp_age)
        @name = temp_name
        @@person_number = @@person_number + 1
    end
    def print_person_number
        return @@person_number
    end
end
# 实例变量
p1 = person.new("zhangsan",24)
p p1.print_person_number
输出结果:1

全局变量

以$开头,它就是一个全局变量,例如:

$first_name $population

2.2 常量

常量以大写字母开头,如果遇到命名多词组合常量,可以使用驼峰命名法,也可以使用下划线分割且所有字母大写。

a string firstname first_name

2.3 方法

方法名

ruby中的方法名遵从与局部变量相同的规则和约定。例如:

def get_first_name
   return @first_name
end

方法调用

方法调用使用.运算符。例如:

p1.get_name   #方法调用 
p1.name    #属性调用

2.4 引用ruby文件

可以使用$:查看加载路径。
这里主要介绍三种引用方式:load、require、require_relative。

load

load命令总是会加载所请求的文件,不论这个文件是否已经加载过。假如一个文件在几次加载过程中发生改变,那么最新版本的文件将优先使用并覆盖之前加载的版本。尤其是在irb会话中,当在编辑器中修改一个文件时,想要立即测试修改的效果,使用load非常有用。

require

经常会使用的一个技术,用于请求ruby扩展或库,不论是标准库还是三方库。
requrire就算调用多次也不会重新加载已经加载过的文件。ruby会持续追踪已经被请求的那些文件而不会重复加载它们。
require不能辨识出当前的工作目录(.)。用户可以显式地指定它。例如:

require "./loadee.rb"
or
$: << "." #把当前目录添加到加载路径当中。
require "loadee.rb"

require_relative

这个命令会搜索相对于所在文件的目录来加载功能。这个不用把当前目录添加到加载路径中。

2.5 数据结构

查看某个属性或者变量是什么类型,可以使用.class方法。

2.5.1 字符串

字符串插值:

name = "zhangsan"
age = "20"
person_desc = "my name is #{name},age is #{age}"
puts person_desc

bang方法:

ruby的方法可以以惊叹号(!)结尾,这样的方法称为bang方法。有惊叹号的方法被标记为危险的。因为他可能会改变原有数据的值。例如:

str = "hello world"
p str.upcase!  
p str
#----------------------
p str.upcase
p str

更多字符串方法参见:https://ruby-doc.org/core-2.2.0/string.html

2.5.2 集合

set不是ruby的核心类,它是一个标准库类,所以使用的时候需要require "set"。它的对象是唯一的。

构造一个集合:

require 'set'
s = [1,2,3,4,5,6,7,8,9,124,45,6,4,1]
set = set.new(s)
p set

集合没有字面构造器。

2.5.3 数组

数组的创建:

#中括号创建 
["zhangsan","lisi","wangwu"]

注意%w 和%w的区别:

name = "tim"
students = %w{zhangsan lisi wangwu #{name}}
students = %w{zhangsan lisi wangwu #{name}}

%w:创建字符串数组的特殊方式

%w:如果想要对字符串进行解析,使用w

数组遍历:

[1,2,3,4,5,8].each {|item| puts item+"!"}

更多数组方法参见:https://docs.ruby-lang.org/en/2.0.0/array.html

2.5.4 散列

散列在其他语言中有时被称为:字典或者map。散列由键值组成。例如:

state_hash = {"january" => "jan","february" => "feb","march" => "mar"}
state_hash["april"] = "apr"
puts state_hash["april"]   #result is apr
puts state_hash.class #result is hash

2.5.5 符号

符号是ruby内置类symbol的实例。它有一个字面构造器:冒号引导符。可以通过这个记号,从字面航辨认出符号与字符串、变量名、方法名或者其他的区别。

符号的特点:

  1. 不变性。符号是不可变的。符号不能添加字符,一旦它存在,就不能修改
  2. 唯一性。符号是唯一的。无论何时看到:abc,看到的都是同一个对象

实践

符号最常用的用法:方法参数和散列键:

#方法参数
puts "abc".send(:upcase)   #等价于puts "abc".send(upcase.to_sym)
#输出结果:abc
#--------------------
#散列键
d_hash = {:name => "zhangsan", :age => 25}
puts d_hash[:age]
#输出结果:25

使用符号的好处:

1.ruby处理符号更快,因此如果要大量处理散列的查找,就会节省一些时间。如果需要性能上的优化,使用符号作为散列键则可能是个好办法。

2.ruby允许一种特殊的符号表现形式在散列键的位置出现,它可以在符号之后使用冒号,同事可以替代散列的分割箭头符,例如:

d_hash = {name: "zhangsan",age: 23}
#等价于
d_hash = {"name" => "zhangsan","age" => 23}

2.6 类和对象

2.6.1 创建类

class student
    attr_accessor :s_name,:s_age, :s_class
    def initialize(name,age,t_class)
        @s_name =  name
        @s_age = age
        @s_class = t_class
    end
    def study
        puts "study"
    end
end
 
s1 = student.new("zhangsan",15,"1年级")
p s1.s_name
s1.study

2.6.2 类的继承

ruby语言遵从单继承原则,无法继承多个类,也就意味着它只是一个超类。

class student < people
end

2.6.3 给类添加属性

原始添加方法:

class ticket
   def initialize(ve,date)
      @venue = ve
      @date = date
   end
   def price=(pr)
      @price = pr
   end
 
   def venue
      @venue
   end
 
   def date
      @date
   end
 
   def price
      @price
   end
 
end

attr_reader & attr_writer

class ticket
   attr_reader :venue, :date, :price   #读取方法
   attr_writer :venue, :date, :price   #写方法
   def initialize(ve,date)
      @venue = ve
      @date = date
   end
 
end
 
ti = ticket.new("北京大学","2019-09-01")
ti.venue = "sdfsdfd"
puts ti.venue

attr_accessor

class ticket
    attr_accessor :price,:venue,:date
    def initialize(ve,date)
        @venue = ve
        @date = date
    end
end
ti = ticket.new("北京大学","2019-09-01")
ti.price = 200
puts ti.price

区别于attr,attr: price只生成了reader,attr: price,true会生成getter和setter。

2.7 模块

ruby鼓励读者进行模块化设计:将大的组件分解为小的,并可以混合(mixin)和匹配对象的行为。和类一样,模块是一组方法和常量的集合。

模块是使用混合到类的方式。

模块没有实例

创建模块使用module关键字:

module category
    def say_hello
        puts "category's hello"
    end
end
class student
    include category    #引用模块
    def initialize
         
    end
end
st = student.new
st.say_hello

2.7.1 include vs prepend

module modulegoone
    def go
        puts "modulegoone's go"
    end
end
module modulegotwo
    def go
        puts "modulegotwo's go"
    end
end
class student < person
    include modulegoone
    prepend modulegotwo
    def go
        puts "student's go"
    end
end
st = student.new
st.goto
# result is modulegotwo's go

方法查找规则

module modulegoone
    def go
        puts "modulegoone's go"
    end
end
 
module modulegotwo
    def go
        puts "modulegotwo's go"
    end
end
 
 
class person
    def go
        puts "person's go"
    end
end
 
class student < person
    include modulegoone
    prepend modulegotwo
    def go
        puts "student's go"
    end
end
st = student.new
st.go

方法查找规则:

Ruby入坑指南

1.先查找当前类中是否有该方法,如果有,则直接调用,执行完毕;

2.查找module中是否有该方法,如果有,则调用,执行完毕;

3.查找父类中是否有该方法,父类中是否有module,如果有prepend模块,则先调用,没有的话如果有在类中定义,则调用;

4.所属的超类

5.内置kernel模块

6.basicobject

7.method_missing nomethoderror

2.8 ruby块yield

块由大量代码组成。

块中的代码总是包含在大括号内

块的调用:需要与其相同名称的方法调用

可以使用yield语句来调用块

每个ruby源文件可以声明当文件被加载时要运行的代码块(begin),以及程序完成执行后要运行的代码块(end)。

begin {
    puts "begin..."
}
end {
    puts "end......."
}
def test
    yield
end
 
test {puts "hello"}
=begin
def test
    puts "在test方法内"
    yield
    puts "又回到了test方法"
    yield
end
test {puts "你在块内"}
=end
 
=begin
def test
    puts "在test方法内"
    yield 10
    puts "又回到了test方法"
    yield 20
end
test {|i| puts "你在块内#{i}"}
=end

3 itools

3.1 介绍

它是一个指令集,里面包含了一些比较实用的命令,可以方便用户的一些操作,例如:查找无用图片、查找无用类、在某个文件或者文件夹中查找某个字符串、查找某个文件等。

链接:

3.2 安装

gem install itools

3.3 使用

name
    itools - a collection of tools for ios developer

synopsis
    itools [global options] command [command options] [arguments...]

version
    0.4.7

global options
    --help    - show this message
    --version - display the program version

commands
    count_code_line    - count lines of code
    find               - search unuse image
    help               - shows a list of commands or help for one command
    parse              - analyze the memory footprint of each part or component in xcode project
    pre_commit         - 通过执行该命令,hook 本地commit,然后进行规范化
    search             - search str(or strs) in some file(or folder's file)
    search_file        - search file in folder
    search_unuse_class - search unuse class
    size_for           - calculate the memory footprint of file or folder(contain file)

更多参见:https://github.com/scottzg/itools

4 推荐

4.1 网站

1.gems:

2.官方文档:

4.2 书籍

1.《ruby程序员修炼之道》

5 附

5.1 预定义全局变量表

pre-defined variables
$!         the exception information message set by 'raise'.
$@         array of backtrace of the last exception thrown.
$&         the string matched by the last successful match.
$`         the string to the left  of the last successful match.
$'         the string to the right of the last successful match.
$+         the highest group matched by the last successful match.
$1         the nth group of the last successful match. may be > 1.
$~         the information about the last match in the current scopke.
$=         the flag for case insensitive, nil by default.
$/         the input record separator, newline by default.
$\         the output record separator for the print and io#write. default is nil.
$,         the output field separator for the print and array#join.
$;         the default separator for string#split.
$.         the current input line number of the last file that was read.
$<         the virtual concatenation file of the files given on command line (or from $stdin if no files were given).
$>         the default output for print, printf. $stdout by default.
$_         the last input line of string by gets or readline.
$0         contains the name of the script being executed. may be assignable.
$*         command line arguments given for the script sans args.
$$         the process number of the ruby running this script.
$?         the status of the last executed child process.
$:         load path for scripts and binary modules by load or require.
$"         the array contains the module names loaded by require.
$debug     the status of the -d switch.
$filename  current input file from $<. same as $<.filename.
$load_path the alias to the $:.
$stderr    the current standard error output.
$stdin     the current standard input.
$stdout    the current standard output.
$verbose   the verbose flag, which is set by the -v switch.
$-0        the alias to $/.
$-a        true if option -a is set. read-only variable.
$-d        the alias to $debug.
$-f        the alias to $;.
$-i        in in-place-edit mode, this variable holds the extension, otherwise nil.
$-i        the alias to $:.
$-l        true if option -l is set. read-only variable.
$-p        true if option -p is set. read-only variable.
$-v        the alias to $verbose.
$    -w        true if option -w is set.

5.2 解释器的命令行开关

usage: ruby [switches] [--] [programfile] [arguments]
  -0[octal]       specify record separator (\0, if no argument)
  -a              autosplit mode with -n or -p (splits $_ into $f)
  -c              check syntax only
  -cdirectory     cd to directory before executing your script
  -d              set debugging flags (set $debug to true)
  -e 'command'    one line of script. several -e's allowed. omit [programfile]
  -eex[:in]       specify the default external and internal character encodings
  -fpattern       split() pattern for autosplit (-a)
  -i[extension]   edit argv files in place (make backup if extension supplied)
  -idirectory     specify $load_path directory (may be used more than once)
  -l              enable line ending processing
  -n              assume 'while gets(); ... end' loop around your script
  -p              assume loop like -n but print line also like sed
  -rlibrary       require the library before executing your script
  -s              enable some switch parsing for switches after script name
  -s              look for the script using path environment variable
  -t[level=1]     turn on tainting checks
  -v              print version number, then turn on verbose mode
  -w              turn warnings on for your script
  -w[level=2]     set warning level; 0=silence, 1=medium, 2=verbose
  -x[directory]   strip off text before #!ruby line and perhaps cd to directory
  -h              show this message, --help for more info

转载请注明出处: