IT@程序员猿媛Ruby学习之路Ruby

Java转Ruby【快速入门】

2019-04-26  本文已影响12人  我没有三颗心脏

最近参加实习了,公司的技术栈中需要用到 Ruby 以及 Rails 框架,所以算是开始了踩坑之旅吧..

Ruby 简介

网上的简介要搜都能搜到,具体涉及的包括历史啦之类这里不再赘述,提几个关键词吧:

对于准备迈入 Ruby 的 Java 程序员来说,有几个地方需要特别的去了解一下。

为什么是 Ruby ?

如果你再稍微花一些心思搜索一下 Ruby on Rails 这个 Web 开发框架,并且打开一些详细说明了体验之后的文章或者是多年经验开发者的分享,你可能会对它产生一些兴趣,这一Part就留着之后介绍了,这也是为以后学习 RoR 框架做准备的。

总之我们要明确我们目的:知道最基本的语法,理解其中的一些关键概念即可。

Ruby 初体验

Mac OX 中有默认的 Ruby 环境,我们可以来一个最短的 "Hello World" 程序,首先在控制台中输入 irb 命令,然后输入 puts "Hello World!" 命令:

irb
irb(main):001:0> puts "Hello World!"
Hello World!
=> nil

你就能看到紧跟着你的输入会有一个 Hello World! 的输出以及一个 nil (对应 Java 中的 null)的返回。

再来一个更加复杂的例子,我们这一次来创建一个数组然后循环输出它:

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 到 Ruby

Java 非常成熟,并且通过 Spring 的加持得到了许多企业的青睐,但是不知道大家有没有感受到一点:它或许有些啰嗦...(我乱说的啊,我也不知道,别问我啊..)从 Java 到 Ruby 据说可以预见性的将代码的规模量大大缩小,因此也能使用更少的时间来输出产品原型。

相似点

Ruby 与 Java 有一些相似的地方...

不同点

Ruby 与 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 的基础上还能养成一个良好的编码习惯。

学习之前必备 - 代码规范

或许有些语句还不能理解,没关系,有一个基础印象就好。

# 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
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'
# bad
if condition
  result = x
else
  result = y
end

# good
result =
  if condition
    x
  else
    y
  end
# boolean expression
if some_condition && some_other_condition
  do_something
end

# control flow
document.save? or document.save!
# bad
unless success?
  puts 'failure'
else
  puts 'success'
end

# good
if success?
  puts 'success'
else
  puts 'failure'
end
# bad
if (x > 10)
  # body omitted
end

# good
if x > 10
  # body omitted
end
# 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
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
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
# 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
# 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
# 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
# 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)
# good and also fast
html = ''
html << '<h1>Page title</h1>'

paragraphs.each do |paragraph|
  html << "<p>#{paragraph}</p>"
end

基于下面链接简化了大部分,因为有一些编码风格能从 Java 自然的切换过来,而且我们也可以使用相应的工具来检查我们的代码,更多可以看这里:https://ruby-china.org/wiki/coding-style

Ruby 语言基础

其实通过上面的语法规范,我们或多或少能感知到一些 Ruby 的语法,有一些细节的地方可以自行去菜鸟教程or其他网站能看到,下面我们就着一些重要的东西快速的学习一遍吧..

数据类型

Ruby 中有以下几种不同的数据类型:

: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 有四种类型的变量,变量的命名方式决定了变量的种类

示例:

$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

示例:

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_namelast_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 标记可以通过模块的 publicprivate 更改。

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

上一篇 下一篇

猜你喜欢

热点阅读