最近參加實習了,公司的技術棧中須要用到 Ruby 以及 Rails 框架,因此算是開始了踩坑之旅吧..html
網上的簡介要搜都能搜到,具體涉及的包括歷史啦之類這裏再也不贅述,提幾個關鍵詞吧:java
對於準備邁入 Ruby 的 Java 程序員來講,有幾個地方須要特別的去了解一下。git
若是你再稍微花一些心思搜索一下 Ruby on Rails 這個 Web 開發框架,而且打開一些詳細說明了體驗以後的文章或者是多年經驗開發者的分享,你可能會對它產生一些興趣,這一Part就留着以後介紹了,這也是爲之後學習 RoR 框架作準備的。程序員
總之咱們要明確咱們目的:知道最基本的語法,理解其中的一些關鍵概念便可。github
Mac OX 中有默認的 Ruby 環境,咱們能夠來一個最短的 "Hello World" 程序,首先在控制檯中輸入 irb
命令,而後輸入 puts "Hello World!"
命令:shell
irb irb(main):001:0> puts "Hello World!" Hello World! => nil
你就能看到緊跟着你的輸入會有一個 Hello World!
的輸出以及一個 nil
(對應 Java 中的 null
)的返回。express
再來一個更加複雜的例子,咱們這一次來建立一個數組而後循環輸出它:編程
irb(main):002:0> properties = ['name','age','sex'] => ["name", "age", "sex"] irb(main):003:0> properties => ["name", "age", "sex"] irb(main):005:0> properties.each {|property| puts "This is #{property}."} This is name. This is age. This is sex. => ["name", "age", "sex"]
不知道感受如何?至少咱們能夠直觀的感覺到:數組
=
就好Java 很是成熟,而且經過 Spring 的加持獲得了許多企業的青睞,可是不知道你們有沒有感覺到一點:它或許有些囉嗦...(我亂說的啊,我也不知道,別問我啊..)從 Java 到 Ruby 聽說能夠預見性的將代碼的規模量大大縮小,所以也能使用更少的時間來輸出產品原型。安全
Ruby 與 Java 有一些類似的地方...
Ruby 與 Java 不一樣的地方...
end
關鍵字,而不使用花括號包裹代碼塊。require
代替 import
。a = [1,2,3]
而不是 int[] a = {1,2,3};
)。foo = Foo.new("hi")
建立新對象,而非 Foo foo = new Foo("hi")
。nil
替代 null
。==
和 equals()
的處理方式與 Java 不同。測試相等性使用 ==
(Java 中是 equals()
)。測試是否爲同一對象使用 equals?()
(Java 中是 ==
)。以上的相同與不一樣來自:https://www.ruby-lang.org/zh_cn/documentation/ruby-from-other-languages/to-ruby-from-java/
延伸閱讀:https://gquintana.github.io/2017/01/08/From-Java-to-Ruby.html
在大體瞭解了 Ruby 一些基礎信息以後,咱們開始 Ruby 基礎語法的學習,雖然面對一門新的語言,語法啊特性啊之類的瞭解頗有必要,但仍是想在瞭解以前看一看 Ruby 的一些代碼規範,好讓本身能快速瞭解 Ruby 的基礎上還能養成一個良好的編碼習慣。
或許有些語句還不能理解,不要緊,有一個基礎印象就好。
通常來說,Ruby 中的變量名和方法名使用下劃線命名法(小寫字母 + _
),類名和模塊名使用 Java 相似的駝峯命名法
每一個縮進級別使用兩個 space(又名軟 tabs),不要使用硬 tabs
# bad - four spaces def some_method do_something end # good def some_method do_something end
;
來分割語句和表達式。以此推論 - 一行使用一個表達式# bad puts 'foobar'; # superfluous semicolon puts 'foo'; puts 'bar' # two expression on the same line # good puts 'foobar' puts 'foo' puts 'bar' puts 'foo', 'bar' # this applies to puts in particular
# bad def too_much; something; something_else; end # okish - notice that the first ; is required def no_braces_method; body end # okish - notice that the second ; is optional def no_braces_method; body; end # okish - valid syntax, but no ; make it kind of hard to read def some_method() body end # good def some_method body end
空方法是這個規則的例外。
# good def no_op; end
# bad - pretty convoluted kind = case year when 1850..1889 then 'Blues' when 1890..1909 then 'Ragtime' when 1910..1929 then 'New Orleans Jazz' when 1930..1939 then 'Swing' when 1940..1950 then 'Bebop' else 'Jazz' end result = if some_cond calc_something else calc_something_else end # good - it's apparent what's going on kind = case year when 1850..1889 then 'Blues' when 1890..1909 then 'Ragtime' when 1910..1929 then 'New Orleans Jazz' when 1930..1939 then 'Swing' when 1940..1950 then 'Bebop' else 'Jazz' end result = if some_cond calc_something else calc_something_else end # good (and a bit more width efficient) kind = case year when 1850..1889 then 'Blues' when 1890..1909 then 'Ragtime' when 1910..1929 then 'New Orleans Jazz' when 1930..1939 then 'Swing' when 1940..1950 then 'Bebop' else 'Jazz' end result = if some_cond calc_something else calc_something_else end
def some_method data = initialize(options) data.manipulate! data.result end def some_methods result end
# bad == begin comment line another comment line == end # good # comment line # another comment line
# bad def some_method() # body omitted end # good def some_method # body omitted end # bad def some_method_with_arguments arg1, arg2 # body omitted end # good def some_method_with_arguments(arg1, arg2) # body omitted end
for
, 除非你知道使用它的準確緣由。大多數時候迭代器均可以用來替 for
。for
是由一組 each
實現的 (所以你正間接添加了一級),可是有一個小道道 - for
並不包含一個新的 scope (不像 each
)而且在它的塊中定義的變量在外面也是能夠訪問的。(這裏有些像 Java 中不用 for-each 語句相似,感興趣的也能夠去搜一搜)arr = [1, 2, 3] # bad for elem in arr do puts elem end # note that elem is accessible outside of the for loop elem #=> 3 # good arr.each { |elem| puts elem } # elem is not accessible outside each's block elem #=> NameError: undefined local variable or method `elem'
if
and case
是表達式這樣的事實它們返回一個結果。# bad if condition result = x else result = y end # good result = if condition x else y end
&&/||
, and/or
用於控制流程。(經驗Rule:若是你必須使用額外的括號(表達邏輯),那麼你正在使用錯誤的的操做符。)# boolean expression if some_condition && some_other_condition do_something end # control flow document.save? or document.save!
unless
和 else
組合。將它們改寫成確定條件。# bad unless success? puts 'failure' else puts 'success' end # good if success? puts 'success' else puts 'failure' end
if/unless/while
的條件。# bad if (x > 10) # body omitted end # good if x > 10 # body omitted end
module
,而不是隻有類方法的 class
。類別應該只在建立實例是合理的時候使用。# bad class SomeClass def self.some_method # body omitted end def self.some_other_method end end # good module SomeClass module_function def some_method # body omitted end def some_other_method end end
class
方法時,偏心使用 module_function
賽過 extend self
。module Utilities extend self def parse_something(string) # do stuff here end def other_utility_method(number, string) # do some more stuff end end # good module Utilities module_function def parse_something(string) # do stuff here end def other_utility_method(number, string) # do some more stuff end end
to_s
方法, 用來表現這個類(實例)對象包含的對象.class Person attr_reader :first_name, :last_name def initialize(first_name, last_name) @first_name = first_name @last_name = last_name end def to_s "#@first_name #@last_name" end end
Struct.new
, 它能夠定義一些瑣碎的 accessors
, constructor
(構造函數) 和 comparison
(比較) 操做。# good class Person attr_reader :first_name, :last_name def initialize(first_name, last_name) @first_name = first_name @last_name = last_name end end # better class Person < Struct.new(:first_name, :last_name) end
Struct.new
,它替你定義了那些瑣碎的存取器(accessors),構造器(constructor)以及比較操做符(comparison operators)。# good class Person attr_accessor :first_name, :last_name def initialize(first_name, last_name) @first_name = first_name @last_name = last_name end end # better Person = Struct.new(:first_name, :last_name) do end
不要去 extend
一個 Struct.new
- 它已是一個新的 class
。擴展它會產生一個多餘的 class
層級 而且可能會產生怪異的錯誤若是文件被加載屢次。
鴨子類型(duck-typing)優於繼承。
# bad class Animal # abstract method def speak end end # extend superclass class Duck < Animal def speak puts 'Quack! Quack' end end # extend superclass class Dog < Animal def speak puts 'Bau! Bau!' end end # good class Duck def speak puts 'Quack! Quack' end end class Dog def speak puts 'Bau! Bau!' end end
當訪問一個數組的第一個或者最後一個元素,傾向使用 first 或 last 而不是 [0] 或 [-1]。
優先使用 字符串插值
來代替 字符串串聯
。
# bad email_with_name = user.name + ' <' + user.email + '>' # good email_with_name = "#{user.name} <#{user.email}>" # good email_with_name = format('%s <%s>', user.name, user.email)
在對象插值的時候不要使用 Object#to_s
,它將會被自動調用。
操做較大的字符串時, 避免使用 String#+
作爲替代使用 String#<<
。就地級聯字符串塊老是比 String#+
更快,它建立了多個字符串對象。
# good and also fast html = '' html << '<h1>Page title</h1>' paragraphs.each do |paragraph| html << "<p>#{paragraph}</p>" end
RuboCop
RuboCop 是一個基於本指南的 Ruby 代碼風格檢查工具。 RuboCop 涵蓋了本指南至關大的部分,支持 MRI 1.9 和 MRI 2.0,並且與 Emacs 整合良好。
基於下面連接簡化了大部分,由於有一些編碼風格能從 Java 天然的切換過來,並且咱們也可使用相應的工具來檢查咱們的代碼,更多能夠看這裏:https://ruby-china.org/wiki/coding-style
其實經過上面的語法規範,咱們或多或少能感知到一些 Ruby 的語法,有一些細節的地方能夠自行去菜鳥教程or其餘網站能看到,下面咱們就着一些重要的東西快速的學習一遍吧..
Ruby 中有如下幾種不一樣的數據類型:
數字/ 字符串/ 符號/ 哈希/ 數組/ 布爾
比較在乎的是 Ruby 並無 Java 中的枚舉類型,多是出於安全方面的考慮吧..(我也不知道...)
符號就像字符串。一個符號以前是冒號(:
)。例如:
:abcd
它們不包含空格。 含有多個單詞的符號用(_
)寫成。 字符串和符號之間的一個區別是,若是文本是一個數據,那麼它是一個字符串,但若是它是一個代碼,它是一個符號。
符號是惟一的標識符,表示靜態值,而字符串表示更改的值。
示例:
irb(main):011:0> "string".object_id => 26922000 irb(main):012:0> "string".object_id => 29115220 irb(main):013:0> :symbol.object_id => 788188 irb(main):014:0> :symbol.object_id => 788188
=>
符號分配。 鍵/值對之間用逗號分隔,全部對都用大括號括起來。 例如:{"key1" => "value1", "key2" => "Chemistry", "key3" => "Maths"}
示例:
data = {"key1" => "Physics", "key2" => "Chemistry", "key3" => "Maths"} puts data["key1"] puts data["key2"] puts data["key3"]
執行上述代碼,獲得如下結果:
Physics Chemistry Maths
Ruby 有四種類型的變量,變量的命名方式決定了變量的種類:
局部變量
以英文小寫字母或者 _
開頭,做用域等同於 Java 局部變量。
全局變量
以 $
開頭,做用域等同於 Java 全局變量。只要全局變量的名稱相同,無論變量在程序的哪一個部分使用,程序都認爲是它們是同一個變量。未初始化的全局變量的值會被初始化爲:nil
。建議不要使用全局變量,由於它們使程序變得祕密和複雜。
示例:
$global_var = "GLOBAL" class One def display puts "Global variable in One is #$global_var" end end class Two def display puts "Global variable in Two is #$global_var" end end oneobj = One.new oneobj.display twoobj = Two.new twoobj.display
執行代碼輸出結果以下:
Total number of states written: 4 Total number of states written: 4 Total number of states written: 4 Total number of states written: 4
@
開頭,在同一個實例中,程序能夠超越方法定義,任意引用、修改實例變量。它屬於類的一個實例,能夠從方法中的類的任何實例訪問。 它們只能訪問一個特定的類的實例。它們不須要初始化,未初始化的實例變量的值是:nil
。示例:
class States def initialize(name) @states_name=name end def display() puts "States name #@states_name" end end # Create Objects first=States.new("Hainan") second=States.new("GuangDong") third=States.new("Beijing") fourth=States.new("ShangDong") # Call Methods first.display() second.display() third.display() fourth.display()
執行代碼輸出結果以下:
States name GuangDong States name Beijing States name ShangDong
@@
開頭,做用域爲該類的全部實例。須要在使用前進行初始化,由類的全部後代共享,未初始化的變量將致使錯誤。示例:
class States @@no_of_states=0 def initialize(name) @states_name=name @@no_of_states += 1 end def display() puts "State name #@state_name" end def total_no_of_states() puts "Total number of states written: #@@no_of_states" end end # Create Objects first=States.new("Assam") second=States.new("Meghalaya") third=States.new("Maharashtra") fourth=States.new("Pondicherry") # Call Methods first.total_no_of_states() second.total_no_of_states() third.total_no_of_states() fourth.total_no_of_states()
執行上面代碼輸出結果以下:
Total number of states written: 4 Total number of states written: 4 Total number of states written: 4 Total number of states written: 4
Object
類是全部 Ruby 對象的默認根。 Ruby 對象繼承自 BasicObject
(它是Ruby中全部類的父類)類,容許建立替代對象層次結構。
首先與 Java 很不一樣的是建立對象:
Object newObject = new Object(); // Java 中新建對象
對比 Ruby:
objectName = className.new
每一個 Ruby 類都是 Class
類的一個實例。一般對於類名,使用駝峯命名規則,類的名稱始終以大寫字母開頭。定義類是用 end
關鍵字完成的。
語法
class ClassName codes... end
咱們使用上面學習過的語法規範來建立一個 Person
類(寫上 to_s
方法):
class Person attr_reader :first_name, :last_name def initialize(first_name, last_name) @first_name = first_name @last_name = last_name end def to_s "#@first_name #@last_name" end end
注意這裏的 attr_reader
對應在 Java 中至關於爲 first_name
和 last_name
定義了 getter
,在 Ruby 中,從對象外部不能直接訪問實例變量或對實例變量賦值,須要經過方法來訪問對象的內部,若是像 Java 那樣一遍一遍爲每個變量寫 getter/setter
就有些冗雜了,Ruby 爲咱們提供了一些方便的存取器。
定義 | 意義 |
---|---|
attr_reader :name | 只讀(定義 name 方法) |
attr_writer :name | 只寫(定義 name= 方法) |
attr_accessor :name | 讀寫(定義以上兩個方法) |
另一點上面有一個很是有趣的規範是使用
Struct.new
來簡化代碼,我以爲很酷也想把它應用在上述 Person 類的建立中,可是發現失敗了(不能在其中定義其餘功能性的代碼),因此可能結論是:這樣的簡化只適用於一些實體類保存數據的類吧。
Ruby 方法使用 def
關鍵字開始,最後還須要使用 end
關鍵字來表示方法定義結束。
語法:
def methodName code... end
示例:
def method_defining(a1 = "Ruby", a2 = "Python") puts "The programming language is #{a1}" puts "The programming language is #{a2}" end method_defining "C", "C++" method_defining
運行上面的代碼執行結果以下:
The programming language is C The programming language is C++ The programming language is Ruby The programming language is Python
方法返回值:
在初探 Ruby 的時候咱們就感覺到,貌似每一條指令都會返回一個返回值,方法也是這樣,在 Ruby 中每一個方法都有一個返回值,這個返回的值將是最後一個語句的值。例如:
def my_method i = 100 j = 10 k = 1 end
上面代碼中,最後方法的返回值是 1
。
Ruby return 語句
Ruby 中的 return
語句用於從 Ruby 方法中返回一個或多個值
示例:
def method i = 100 j = 200 k = 300 return i, j, k end var = method puts var
上面代碼結果以下:
100 200 300
可變參數:
假設聲明一個方法須要兩個參數,每當調用這個方法時,須要傳遞兩個參數。可是,Ruby容許您聲明使用可變數量參數的方法。 讓咱們來看一下這個示例:
def sample (*test) puts "The number of parameters is #{test.length}" for i in 0...test.length puts "The parameters are #{test[i]}" end end sample "Maxsu", "6", "F" sample "Mac", "38", "M", "MCA"
執行上面代碼,獲得以下結果:
The number of parameters is 3 The parameters are Maxsu The parameters are 6 The parameters are F The number of parameters is 4 The parameters are Mac The parameters are 38 The parameters are M The parameters are MCA
類方法:
當方法在類定義以外定義時,默認狀況下該方法被標記爲 private
。 另外一方面,默認狀況下,類定義中定義的方法被標記爲 public
。模塊的默承認見性和 private
標記能夠經過模塊的 public
或 private
更改。
Ruby 給出一種不用實例化一個類就能夠訪問一個方法。下面來看看看如何聲明和訪問類方法 -
class Accounts def reading_charge end def Accounts.return_date end end
訪問類方法 -
Accounts.return_date
Ruby 模塊是方法和常量的集合。暫時你可簡單的理解爲一個不能實例化的類,這樣作的好處是一來能夠提供一個命名空間避免名字衝突,另外一個是實現了 mixin
的功能。
不知道您有沒有發現,Ruby 沒有提供多重繼承的功能,但 Ruby 的模板幾乎消除了多重繼承的須要,提供了一種名爲 mixin
的裝置。
示例:
module A def a1 end def a2 end end module B def b1 end def b2 end end class Sample include A include B def s1 end end samp=Sample.new samp.a1 samp.a2 samp.b1 samp.b2 samp.s1
Ruby 代碼在其餘編程語言中被稱爲閉包。它由一組代碼組成,它們始終用大括號括起來,或者在 do..end
之間書寫。大括號語法老是具備比 do..end
語法更高的優先級。也就是說大括號優先級高,do..end
優先級低。
語法:
block_name{ statement1 statement2 .......... }
yield語句:
def test puts "在 test 方法內" yield puts "你又回到了 test 方法內" yield end test {puts "你在塊內"}
上面代碼運行結果以下:
在 test 方法內 你在塊內 你又回到了 test 方法內 你在塊內
塊和方法:
def test yield end test{ puts "Hello world"}
本實例是實現塊的最簡單的方式。您使用 yield 語句調用 test 塊。
可是若是方法的最後一個參數前帶有 &
,那麼您能夠向該方法傳遞一個塊,且這個塊可被賦給最後一個參數。若是 *
和 &
同時出如今參數列表中,&
應放在後面。
def test(&block) block.call end test { puts "Hello World!"}
上述代碼運行結果以下:
Hello World!
這一部分建議再去看一下慕課網上的教程,看關於第三章的內容便可:Ruby語言快速入門:https://www.imooc.com/learn/765
通過以上簡單的學習,咱們對 Ruby 有了一個大體的瞭解,算是簡單入了個門(有一些簡單的例如循環啊,判斷啊,運算符之類的簡單我就沒有寫了),更多的東西須要本身平時的編碼中去總結學習(確定有一些坑須要本身去填的)。
參考文章:
1.Ruby 教程 - 菜鳥驛站 - http://www.runoob.com/ruby/ruby-intro.html
2.Ruby 教程 - 易百教程 - https://www.yiibai.com/ruby
3.20分鐘體驗 Ruby - https://www.ruby-lang.org/zh_cn/documentation/quickstart/
4.笨方法學 Ruby - https://lrthw.github.io/intro/
5.Ruby 快速入門 - https://wdxtub.com/2016/03/30/ruby-first-step/
按照慣例黏一個尾巴:
歡迎轉載,轉載請註明出處!
簡書ID:@我沒有三顆心臟
github:wmyskxz 歡迎關注公衆微信號:wmyskxz 分享本身的學習 & 學習資料 & 生活 想要交流的朋友也能夠加qq羣:3382693