1 / 71

Ruby for Java Developers

Ruby for Java Developers. Neal Ford Architect Thought Works www.nealford.com www.thoughtworks.com nford@thoughtworks.com Blog: memeagora.blogspot.com. Questions, Slides, and Samples. Please feel free to ask questions anytime The slides and samples will be available at www.nealford.com

elijah
Download Presentation

Ruby for Java Developers

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Ruby for Java Developers Neal Ford Architect ThoughtWorks www.nealford.com www.thoughtworks.com nford@thoughtworks.com Blog: memeagora.blogspot.com

  2. Questions, Slides, and Samples • Please feel free to ask questions anytime • The slides and samples will be available at www.nealford.com • I’ll show that address again at the end

  3. What This Session Covers: • The Ruby Philosophy • Ruby syntax • Classes and objects in Ruby • Closures • Mixins • Networking • Threading • Test-first coding in Ruby • Ruby as a scripting language • Ruby as a web language

  4. What is Ruby? • From www.ruby-lang.org: • Ruby is the interpreted scripting language for quick and easy object-oriented programming. • It has many features to process text files and to do system management tasks (as in Perl). • It is simple, straight-forward, extensible, and portable. • Ruby has: • Simple syntax, partially inspired by Eiffel and Ada • Exception handling features, like Java or Python • operators that are syntax sugar for the methods. You can redefine them easily

  5. Features of Ruby • Ruby is a complete, full, pure object oriented language. • All data in Ruby is an object, in the sense of Smalltalk: no exceptions. • Example: In Ruby, the number 1 is an instance of class Fixnum. • Ruby's OO is carefully designed to be both complete and open for improvements. • Example: Ruby has the ability to add methods to a class, or even to an instance during runtime. A • An instance of one class *can* behave differently from other instances of the same class.

  6. Features of Ruby • Ruby features single inheritance only, *on purpose*. • But Ruby knows the concept of modules (called Categories in Objective-C). • Modules are collections of methods. • Every class can import a module and so gets all its methods for free. • Ruby features true closures. • Not just unnamed function, but with present variable bindings. • Ruby features blocks in its syntax (code surrounded by '{' ... '}' or 'do' ... 'end'). • These blocks can be passed to methods, or converted into closures.

  7. Features of Ruby • Ruby features a true mark-and-sweep garbage collector. • It works with all Ruby objects. • You don't have to care about maintaining reference counts in extension libraries. • Integers in Ruby can (and should) be used without counting their internal representation. • There *are* small integers (instances of class Fixnum) and large integers (Bignum), but you need not worry over which one is used currently. • If a value is small enough, an integer is a Fixnum, otherwise it is a Bignum. Conversion occurs automatically.

  8. Features of Ruby • Ruby needs no variable declarations. • It uses simple naming conventions to denote the scope of variables. • Ruby can load extension libraries dynamically if an OS allows. • Ruby features OS independent threading • Ruby is highly portable: it is developed mostly on Linux, but works on many types of UNIX, DOS, Windows 95/98/Me/NT/2000/XP, MacOS, BeOS, OS/2, etc. var_name => local variable @var_name => instance variable @var_name => global variable

  9. Obtaining Ruby • The main Ruby site: www.ruby-lang.org • For Windows, the One-Click Ruby Installer project on RubyForge: http://rubyinstaller.rubyforge.org/wiki/wiki.pl • If you have Cygwin, you can choose Ruby as one of the language options • There is a specific cygwin-ruby version, optimized for Cygwin • The English reference manual is very outdated • However, http://www.ruby-doc.org/ has up to date RubyDocs and other resources • The Pick-Axe book (shown at the end)

  10. Classes and Objects in Ruby class Employee def initialize(name, salary, hire_year) @name = name @salary = salary @hire_year = hire_year end def to_s "Name is #{@name}, salary is #{@salary}, “ + "hire year is #{@hire_year}" end def raise_salary_by(perc) @salary += (@salary * 0.10) end end

  11. Inheritance class Manager < Employee def initialize(name, salary, hire_year, asst) super(name, salary, hire_year) @asst = asst end def to_s super + ",\tAssistant info: #{@asst}" end def raise_salary_by(perc) perc += 2005 - @hire_year super(perc) end end

  12. Tying It Together def show(emps) emps.each { |e| puts e } end employees = Array.new employees[0] = Employee.new("Homer", 200.0, 1995) employees[1] = Employee.new("Lenny", 150.0, 2000) employees[2] = Employee.new("Carl", 250.0, 1999) employees[3] = Manager.new("Monty", 3000.0, 1950, employees[2]) show(employees) employees.each { |e| e.raise_salary_by(10) } puts "\nGive everyone a raise\n\n" show employees

  13. Class Members class Employee @@num_employees = 0; def Employee.num_employees @@num_employees end def initialize(name, salary, hire_year) @name = name @salary = salary @hire_year = hire_year @@num_employees += 1 end # . . . show employees puts "Number of employees in the company: " + Employee.num_employees.to_s

  14. Properties class Employee def name @name end def salary @salary end def hire_year @hire_year end # . . . emp = Employee.new("Homer", 100.0, 2004) printf "Name: %s\n", emp.name printf "Salary: %d\n", emp.salary printf "Hire Year: %s\n", emp.hire_year

  15. attr_reader class Employee attr_reader :name, :salary, :hire_year def initialize(name, salary, hire_year) @name = name @salary = salary @hire_year = hire_year end # . . . emp = Employee.new("Homer", 100.0, 2004) printf "Name: %s\n", emp.name printf "Salary: %d\n", emp.salary printf "Hire Year: %s\n", emp.hire_year

  16. Writable Properties class Employee def name @name end def name=(new_name) @name = new_name end def salary @salary end def hire_year @hire_year end # . . . emp = Employee.new("Homer", 100.0, 2004) emp.name = "Monty" printf "Name: %s\n", emp.name

  17. attr_writer class Employee attr_reader :name, :salary, :hire_year attr_writer :name, :salary, :hire_year def initialize(name, salary, hire_year) @name = name @salary = salary @hire_year = hire_year end #. . . emp = Employee.new("Homer", 100.0, 2004) emp.name = "Monty" printf "Name: %s\n", emp.name

  18. Singletons class Logger private_class_method :new @@logger = nil def Logger.create @@logger = new unless @@logger @@logger end end puts Logger.create.object_id puts Logger.create.object_id

  19. Access Control • Ruby has 3 levels of access control

  20. Private vs. Protected • The difference is subtle • Protected • Can be called by any instance of the defining class or its subclasses • Private • Called only within the context of the calling object • Never possible to access another object’s private methods directly, even if the object is the same class as the caller

  21. Arrays - General Syntax a = [ 3.14159, "pi", 99 ] a.type » Array a.length » 3 a[0] » 3.14159 a[1] » "pi" a[2] » 99 a[3] » nil b = Array.new b.type » Array b.length » 0 b[0] = "second" b[1] = "array" b » ["second", "array"]

  22. Arrays - Indexing • Negative indices a = [ 1, 3, 5, 7, 9 ] a[-1] » 9 a[-2] » 7 a[-99] » nil • Pairs a = [ 1, 3, 5, 7, 9 ] a[1, 3] » [3, 5, 7] a[3, 1] » [7] a[-3, 2] » [5, 7]

  23. Arrays - Ranges a = [ 1, 3, 5, 7, 9 ] a[1..3] » [3, 5, 7] a[1...3] » [3, 5] a[3..3] » [7] a[-3..-1] » [5, 7, 9]

  24. Array Assignment a = [ 1, 3, 5, 7, 9 ] » [1, 3, 5, 7, 9] a[1] = 'foo' » [1, "foo", 5, 7, 9] a[-3] = 'bar' » [1, "foo", "bar", 7, 9] a[3] = [ 9, 8 ] » [1, "foo", "bar", [9, 8], 9] a[6] = 99 » [1, "foo", "bar", [9, 8], 9, nil, 99]

  25. Array Assignment Ranges a = [ 1, 3, 5, 7, 9 ] » [1, 3, 5, 7, 9] a[2, 2] = 'cat' » [1, 3, "cat", 9] a[2, 0] = 'dog' » [1, 3, "dog", "cat", 9] a[1, 1] = [ 9, 8, 7 ] » [1, 9, 8, 7, "dog", "cat", 9] a[0..3] = [] » ["dog", "cat", 9] a[5] = 99 » ["dog", "cat", 9, nil, nil, 99]

  26. Hashes h = { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' } h.length » 3 h['dog'] » "canine" h['cow'] = 'bovine' h[12] = 'dodecine' h['cat'] = 99 h » {"cow"=>"bovine", "cat"=>99, 12=>"dodecine", "donkey"=>"asinine", "dog"=>"canine"}

  27. Blocks class EmployeeList def initialize @employees = Array.new end def add(an_employee) @employees.push(an_employee) self end def delete_first @employees.shift end def delete_last @employees.pop end

  28. Blocks def show @employees.each { |e| puts e } end def [](key) if key.kind_of?(Integer) @employees[key] end end end list = EmployeeList.new list.add(Employee.new("Homer", 200.0, 1995)). add(Employee.new("Lenny", 150.0, 2000)). add(Employee.new("Carl", 250.0, 1999)) list.show puts "Employee #1 is " + list[0].to_s

  29. Iterating with for def [](key) if key.kind_of?(Integer) @employees[key] else for i in 0..@employees.length return @employees[i] if key == @employees[i].name end end return nil end end list = EmployeeList.new list.add(Employee.new("Homer", 200.0, 1995)). add(Employee.new("Lenny", 150.0, 2000)). add(Employee.new("Carl", 250.0, 1999)) list.show puts "Employee #1 is " + list[0].to_s puts "Employee named 'Homer' is " + list["Homer"].to_s

  30. Using Blocks def [](key) if key.kind_of?(Integer) result = @employees[key] else result = @employees.find{ |anEmp| key == anEmp.name } end return result end end puts "Employee #1 is " + list[0].to_s puts "Employee named 'Homer' is " + list["Homer"].to_s

  31. The Ruby Way def [](key) return @employees[key] if key.kind_of?(Integer) return @employees.find { |anEmp| key == anEmp.name } end end list = EmployeeList.new list.add(Employee.new("Homer", 200.0, 1995)). add(Employee.new("Lenny", 150.0, 2000)). add(Employee.new("Carl", 250.0, 1999)) list.show puts "Employee #1 is " + list[0].to_s puts "Employee named 'Homer' is " + list["Homer"].to_s

  32. Building Iterators def fib_up_to(max) i1, i2 = 1, 1 # parallel assignment while i1 <= max yield i1 i1, i2 = i2, i1+i2 end end fib_up_to(1000) { |f| print f, " " }

  33. Blocks for Transactions class File def File.open_and_process(*args) f = File.open(*args) yield f f.close() end end File.open_and_process("testfile", "r") do |aFile| print while aFile.gets end

  34. Blocks for Transactions, Take 2 class File def File.myOpen(*args) aFile = File.new(*args) # If there's a block, pass in the file and close # the file when it returns if block_given? yield aFile aFile.close aFile = nil end return aFile end end

  35. Closures • Closures represent a (nameless) block of code that retains its context, even if the context is out of scope • A closure object has code to run, the executable, and state around the code, the scope. • You can refer to the local variables inside a closure. • Even after the function has returned, and its local scope has been destroyed, the local variables remain in existence as part of the closure object. • When no one refers to the closure anymore, it's garbage collected, and the local variables go away.

  36. Closure Example def make_counter var = 0 proc do # coverts a block to a proc object var +=1 end end c1 = make_counter c1.call c1.call c1.call c2 = make_counter puts "c1 = #{c1.call}, c2 = #{c2.call}" # output: c1 = 4, c2 = 1

  37. Regular Expressions • Regular expressions are a built-in data type in Ruby a = Regexp.new('^\s*[a-z]') » /^\s*[a-z]/ b = /^\s*[a-z]/ »/^\s*[a-z]/ c = %r{^\s*[a-z]} » /^\s*[a-z]/ a = "Fats Waller" a =~ /a/ » 1 a =~ /z/ » nil a =~ "ll" » 7

  38. Extending Classes • Classes are never closed in Ruby • You can add new methods to user or system classes • Just open the definition and start typing! class String def rot(num = 13) return self.split("").collect { |ch| if /^[a-z]$/ === ch ((ch[0] + num - 'a'[0]) % 26 + 'a'[0]).chr elsif /^[A-Z]$/ === ch ((ch[0] + num - 'A'[0]) % 26 + 'A'[0]).chr else ch end }.join("") end alias rot13 rot end

  39. Conditionals • True in Ruby implies • Any value that is not nil or the constant false • Zero is not false • A zero-length string is not false • Ruby includes an operator defined? • Returns nil if its argument (which can be an arbitrary expression) is not defined • Otherwise returns a description of the argument defined? 1 » "expression" defined? dummy » nil defined? printf » "method" defined? String » "constant"

  40. Comparison Operators

  41. if Expression • General form: if emp.name == "Homer" then handle = "slacker" elsif emp.name == "Lenny" then handle = "go-getter" else handle = "unknown" end

  42. if Expression • If you lay them out on separate lines, you can skip the then keyword if emp.name == "Homer" handle = "slacker" elsif emp.name == "Lenny" handle = "go-getter" else handle = "unknown" end

  43. if Expression • You can use if as an expression if you want handle = if emp.name == "Homer" then "slacker" elsif emp.name == "Lenny" then "go-getter" else "unknown" end

  44. unless, Conditional Expressions • The unless expression is a negated if statement unless emp.salary > 2000 then raise_percentage = 0.10 else raise_percentage = 0.11 end • There is also the ternary operator raise_percentage = empl.salary > 2000 ? 0.10 : 0.11

  45. If and Unless Modifiers • Like Perl, statement modifiers allow you to attach conditional statements onto the end of a normal statement mon,day,year = $1,$2,$3 if /(\d\d)-(\d\d)-(\d\d)/ puts "a = #{a}" if debug print total unless total == 0 while gets next if /^#/ # Skip comments parseLine unless /^$/ # Don't parse empty lines end

  46. Case Expressions case inputLine when "debug" dumpDebugInfo dumpSymbols when /p\s+(\w+)/ dumpVariable($1) when "quit", "exit" exit else print "Illegal command: #{inputLine}" end

  47. Case + Regular Expressions case line when /name=(.*)/ puts "Name is #$1" when /salary=(.*)/ puts "Salary is #$1" when /Hire\sYear=(.*)/ puts "Hire Year is #$1" end

  48. Loops • While loop while gets # . . . end • Until loop until emp.salary > 2500 employee_list.add(emp.pop) end

  49. Loops as Modifiers a *= 2 while a < 100 a -= 10 until a < 100

  50. Iterators 3.times do print "knock " end # knock knock knock 0.upto(9) do |x| print x, " " end #0 1 2 3 4 5 6 7 8 9 0.step(12, 3) {|x| print x, " " } # 0, 3, 6, 9, 12

More Related