Ruby七天入門(2 函數,數組和類),ruby七天

來源:互聯網
上載者:User

Ruby七天入門(2 函數,數組和類),ruby七天
DAY 2

第二天學習繼續,今天重點學習函數,集合和類等編程的基本要素。

2.1 函數2.1.1 簡單定義
 def tell_me puts true end
  • 定義一個簡單的函數(無參無傳回值)很簡單,使用def end包裹函數體即可。
2.1.2 參數
def tell_me(a)puts aendtell_me 11=> nil
  • 使用參數和其他語言類似,加括弧加變數名即可。
2.1.2.1 參數預設值

同樣可以指定參數預設值:

def tell_me(a='1',b)puts aputs bend=> niltell_me 212=> niltell_me 3,434=> nil

我們看到指定預設值的方式跟其他語言類似。

有些苦惱的是,看起來我們需要記住每一個函數的參數數量和含義。

2.1.2.2 可變參數

Ruby同樣支援可變參數,而且因為不受類型的限制,使用相當自由:

def test(*tt)    for i in 0...tt.length        puts tt[i]    endend=> niltest 1,212=> 0...2test 'a'a=> 0...1
  • 我們看到只需要將參數前加*即可,收到的參數就將是一個數組。
2.1.3 傳回值2.1.3.1 預設傳回值
  • 昨天的學習裡看到過,其實所有的Ruby語句都有傳回值,那麼其實我們及時不給函數指定傳回值,函數也會返回他執行的最後一個語句的值。
    看下面的例子:
def give_metrueend=> nili=give_me=> truei=> true

這個函數我們並沒有指定傳回值,但是函數還是返回了最後執行的語句true的值。

2.1.3.2 return語句
$ irbdef testa=1b=2return a,bend=> nilvar=test=> [1, 2]var.class=> Arrayvar=> [1, 2]
  • Ruby可以通過return語句指定傳回值,而且跟C家族語言不同的是,Ruby可以同時返回多個傳回值。

  • 因為動態語言的特性,Ruby看起來如此自由,但是看起來這就更要求調用者對他們的調用負責。

2.2 代碼塊和yield2.2.1 代碼塊的使用

代碼塊是沒有名字的函數。

3.times{puts 'hi'}
  • times是Fixnum類的方法,它可以執行後面的代碼塊n次。
  • 後面大括弧中內容就是代碼塊,代碼塊既可以用{}來包裹,也可以用do/end來包裹,就像下面的的代碼。
3.times doputs '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    endendmy_times(3){puts 'a'}

我們看到這個函數根據傳入參數,調用了一定數量的代碼塊。

  • 函數中定義的yield表示執行代碼塊中的代碼。
2.2.3 代碼塊作為函數參數

我們也可以將代碼塊作為參數一直傳遞下去。

def call_block(&block)    block.callenddef pass_block(&block)    call_block(&block)endpass_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=> Arrayirb(main):003:0> a =[]=> []irb(main):004:0> a[1]=> nilirb(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=> 1irb(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]=> 5irb(main):021:0> a=[]=> []irb(main):022:0> a[1]=8=> 8irb(main):023:0> a[3]=6=> 6irb(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=> 4irb(main):027:0> a=> [nil, 8, nil, 6]

數組同樣支援push和pop,棧頂位於數組尾部。

2.3.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

其實和數組類似,關鍵的不同就在於一個=>符號,符號前面是鍵,後面是值。

map={1=>'one',2=>'two'}a = map.to_aputs a
  • 散列表可以轉化為數組:其中每個元素是一個key, value組成的數組
map.each { |k,v| p "#{k}=>#{v}"  }

散列表同樣可以遍曆

2.5 類

所有的類都有一個共同的祖先,BasicObject。

class TreeTestattr_accessor :children,:node_namedef initialize(name,children=[])    @children = children    @node_name = nameendendruby_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.7實踐

今天實踐在前面Tree類的基礎上加上遍曆訪問的功能,同時我修改了初始化方法,接受散列表和數組嵌套的結構:

class Treeattr_accessor :children,:node_namedef initialize(map={})    @children = []    map.each do |k,v|         @node_name = k        v.each { |key,value|  @children.push(Tree.new({key=>value}))} if v!=nil    endenddef visit_all(&block)    visit(&block)    children.each{|c| c.visit_all(&block)}enddef visit(&block)    block.call(self)endendruby_tree = Tree.new({'grandpa' => { 'dad' => {'child 1' => {}, 'child 2' => {} }, 'uncle'=> {'child 3' => {}, 'child 4' => {} } } } )ruby_tree.visit {|node| puts node.node_name}ruby_tree.visit_all {|node| puts node.node_name}

visit方法傳遞了代碼塊,調用了代碼塊並用self做參數(所以看起來代碼塊是通過這種方式獲得參數?),其實就是列印了調用執行個體的node_name。
visit_all先對當前節點調用了visit方法,然後對子節點進行了遞迴。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.