码迷,mamicode.com
首页 > 编程语言 > 详细

Ruby七天入门(2 函数,数组和类)

时间:2015-02-28 10:18:49      阅读:231      评论:0      收藏:0      [点我收藏+]

标签:ruby   编程   

DAY 2

第二天学习继续,今天重点学习函数,数组和类等编程的基本要素。

2.1 函数

2.1.1 简单定义

 def tell_me
 puts true
 end
  • 定义一个简单的函数(无参无返回值)很简单,使用def end包裹函数体即可。

2.1.2 参数

def tell_me(a)
puts a
end
tell_me 1
1
=> nil
  • 使用参数和其他语言类似,加括号加变量名即可。

2.1.2.1 参数默认值

同样可以指定参数默认值:

def tell_me(a=‘1‘,b)
puts a
puts b
end
=> nil
tell_me 2
1
2
=> nil
tell_me 3,4
3
4
=> nil

我们看到指定默认值的方式跟其他语言类似。

有些苦恼的是,看起来我们需要记住每一个函数的参数数量和含义。

2.1.2.2 可变参数

Ruby同样支持可变参数,而且因为不受类型的限制,使用相当自由:

def test(*tt)
    for i in 0...tt.length
        puts tt[i]
    end
end
=> nil
test 1,2
1
2
=> 0...2
test ‘a‘
a
=> 0...1
  • 我们看到只需要将参数前加*即可,收到的参数就将是一个数组。

2.1.3 返回值

2.1.3.1 默认返回值

  • 昨天的学习里看到过,其实所有的Ruby语句都有返回值,那么其实我们及时不给函数指定返回值,函数也会返回他执行的最后一个语句的值。
    看下面的例子:
def give_me
true
end
=> nil

i=give_me
=> true

i
=> true

这个函数我们并没有指定返回值,但是函数还是返回了最后执行的语句true的值。

2.1.3.2 return语句

$ irb
def test
a=1
b=2
return a,b
end
=> nil
var=test
=> [1, 2]
var.class
=> Array
var
=> [1, 2]
  • Ruby可以通过return语句指定返回值,而且跟C家族语言不同的是,Ruby可以同时返回多个返回值。

  • 因为动态语言的特性,Ruby看起来如此自由,但是看起来这就更要求调用者对他们的调用负责。

2.2 代码块和yield

2.2.1 代码块的使用

代码块是没有名字的函数。

3.times{puts ‘hi‘}
  • times是Fixnum类的方法,它可以执行后面的代码块n次。
  • 后面大括号中内容就是代码块,代码块既可以用{}来包裹,也可以用do/end来包裹,就像下面的的代码。
3.times do
puts ‘hello‘
end

昨天在区间一节中提到的each函数后面其实也是代码块:

names=[‘lee‘,‘tom‘,‘jim‘]
names.each{|a| puts a}

2.2.2 yield执行代码块

下面我们来看下自定义的方法来执行代码块:

def my_times(i=5)
    while i>0
        i=i-1
        yield
    end
end

my_times(3){puts ‘a‘}

我们看到这个函数根据传入参数,调用了一定数量的代码块。
- 函数中定义的yield表示执行代码块中的代码。

2.2.3 代码块作为函数参数

我们也可以将代码块作为参数一直传递下去。

def call_block(&block)
    block.call
end

def pass_block(&block)
    call_block(&block)
end

pass_block{puts ‘hello‘}
  • 在Ruby中,参数名之前加一个“&”,表示将代码块作为闭包传递给函数。闭包就是把函数以及变量包起来,使得变量的生存周期延长。

2.3 数组

animals = [‘lions‘, ‘tigers‘, ‘bears‘]
puts animals[1]
puts animals[-1]
puts animals[0..1]
  • 上面这段代码有个语法糖,-1表示返回倒数第一个元素;当然1和其他语言一样,表示第二个元素
  • animals[0..1]用了昨天学过的区间,表示从0到1个元素
irb(main):002:0> [].class
=> Array
irb(main):003:0> a =[]
=> []
irb(main):004:0> a[1]
=> nil
irb(main):005:0> b[1]
NameError: undefined local variable or method `b‘ for main:Object
        from (irb):5
        from /usr/bin/irb:12:in `<main>‘
irb(main):006:0> a[1] = 1
=> 1
irb(main):007:0> a[0] = ‘zero‘
=> "zero"
irb(main):009:0> a[2]=[‘2‘,‘3‘,[4,5]]
=> ["2", "3", [4, 5]]
irb(main):010:0> a
=> ["zero", 1, ["2", "3", [4, 5]]]
irb(main):011:0> a[2][2]
=> [4, 5]
irb(main):012:0> a[2][2][1]
=> 5
irb(main):021:0> a=[]
=> []
irb(main):022:0> a[1]=8
=> 8
irb(main):023:0> a[3]=6
=> 6
irb(main):024:0> a
=> [nil, 8, nil, 6]

比起大多数语言的数组,Ruby的数组使用很自由,从上面这些代码可以看出来。

  • 数组元素不必有相同类型
  • 可以只定义部分数组元素,其余位置将默认为nil值
  • 需要注意的是,在给数组元素赋值时,需要首先使用a =[]类似语法让a的类型变为数组类型,否则出现上面直接运行 b[1]时报的错误
irb(main):025:0> a.push(4)
=> [nil, 8, nil, 6, 4]
irb(main):026:0> a.pop
=> 4
irb(main):027:0> a
=> [nil, 8, nil, 6]

数组同样支持push和pop,栈顶位于数组尾部。

2.4 散列表

散列表就是键值对,对应java里面的map容器。

irb(main):032:0> map={1=>‘one‘,2=>‘two‘}
=> {1=>"one", 2=>"two"}
irb(main):033:0> map
=> {1=>"one", 2=>"two"}
irb(main):034:0> map[1]
=> "one"
irb(main):035:0> map[3]
=> nil

其实和数组类似,关键的不同就在于一个=>符号,符号前面是键,后面是值。

2.5 类

所有的类都有一个共同的祖先,BasicObject。

class TreeTest
attr_accessor :children,:node_name

def initialize(name,children=[])
    @children = children
    @node_name = name
end
end

ruby_tree = Tree.new("ruby",[Tree.new(‘1‘),Tree.new(‘2‘)])

上面代码定义了一个简单的类。

  • 类命名一般使用骆驼命名法,变量和方法名采用小写下划线命名法,而常量采用全大写形式;用于逻辑测试的函数一般用?结尾
  • 实例变量前需要加@(类似java的this?),而类变量前需要加@@(类似java的类名?)
  • attr关键字可用来定义实例变量。它有几种版本,其中最常用的版本是attr和attr_accessor。attr定义实例变量和访问变量的同名方法,而attr_accessor定义实例变量、访问方法和设置方法。
  • initialize方法有特殊含义,类在初始化一个新对象的时候,会调用这个方法
  • 类初始化时采用类名加.new的方法来初始化

2.6 小结

今天主要学习了Ruby的函数,类,数组的基本使用,最大的感触是Ruby的实现充满了符合直觉的特性,在掌握了基本语法后,很多代码只需要按照尝试着写就可以执行。

2.4实践

今天实践在前面Tree类的基础上加上遍历访问的功能:

class Tree
attr_accessor :children,:node_name

def initialize(name,children=[])
    @children = children
    @node_name = name
end

def visit_all(&block)
    visit(&block)
    children.each{|c| c.visit_all(&block)}
end

def visit(&block)
    block.call(self)
end
end

ruby_tree = Tree.new("ruby",[Tree.new(‘1‘),Tree.new(‘2‘)])
ruby_tree.visit {|node| puts node.node_name}
ruby_tree.visit_all {|node| puts node.node_name}

visit方法传递了代码块,调用了代码块并用self做参数(所以看起来代码块是通过这种方式获得参数?),其实就是打印了调用实例的node_name。
visit_all先对当前节点调用了visit方法,然后对子节点进行了递归。

Ruby七天入门(2 函数,数组和类)

标签:ruby   编程   

原文地址:http://blog.csdn.net/lee_3do/article/details/43981865

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!