440 likes | 575 Views
Ruby and the tools 740Tools05 ClassesObjectsVars. CSCE 740 Software Engineering. Topics Ruby Classes Objects Variables Containers Blocks Iterators. Spring 2014. Tools -. Last Time Ruby Basics Ruby Regexp. New Ruby Classes Objects Next Time: System Modelling.
E N D
Ruby and the tools740Tools05ClassesObjectsVars CSCE 740 Software Engineering • Topics • Ruby Classes • Objects • Variables • Containers • Blocks • Iterators Spring 2014
Tools - • Last Time • Ruby Basics • Ruby Regexp • New Ruby • Classes • Objects • Next Time: System Modelling
Ruby 1.9 “Buy the book page” • http://pragprog.com/book/ruby3/programming-ruby-1-9 • Contents and Extracts • Regular Expressions (download pdf) • Namespaces, Source Files, and Distribution (download pdf) • Built-in Classes and Modules (download pdf of the entry for class Array) • Free Content … • More on reg expr • http://www.ruby-doc.org/core-2.1.0/Regexp.html http://ruby-doc.org/docs/ProgrammingRuby/
google(ruby 1.9 tutorial) • http://ruby-doc.com/docs/ProgrammingRuby/ • http://www.ruby-doc.org/stdlib-1.9.3/
Programming Ruby TOC • ForewordPrefaceRoadmapRuby.newClasses, Objects, and VariablesContainers, Blocks, and IteratorsStandard TypesMore About MethodsExpressionsExceptions, Catch, and ThrowModulesBasic Input and OutputThreads and ProcessesWhen Trouble Strikes • Ruby and Its WorldRuby and the WebRuby TkRuby and Microsoft WindowsExtending RubyThe Ruby LanguageClasses and ObjectsLocking Ruby in the SafeReflection, ObjectSpace, and Distributed RubyBuilt-in Classes and MethodsStandard LibraryObject-Oriented Design LibrariesNetwork and Web LibrariesMicrosoft Windows SupportEmbedded DocumentationInteractive Ruby ShellSupport
Ruby I/O • Already seen • puts • print • P • On reading • Gets reads line from stdin variable $_ • Iterate over lines of file • line = gets • printline http://ruby-doc.org/docs/ProgrammingRuby/
Processing stdin = ARGF • while gets # assigns line to $_ • if /Ruby/ # matches against $_ • print # prints $_ • end • end • Now the “ruby way” • ARGF.each { |line| print line if line =~ /Ruby/ } http://ruby-doc.org/docs/ProgrammingRuby/
Classes, Objects, Variables • Basic Classes: def, to_s • Inheritance and Messages • Inheritance and Mixins • Objects and Attributes • Writable Attributes • Virtual Attributes • Class Variables and Class Methods • Singletons and Other Constructors • Access Control • Variables
Classes, Objects, and Variables • class Song • def initialize(name, artist, duration) • @name = name • @artist = artist • @duration = duration • end • end • aSong = Song.new("Bicylops", "Fleck", 260) http://ruby-doc.org/docs/ProgrammingRuby/
aSong = Song.new("Bicylops", "Fleck", 260) • aSong.inspect>> #<Song:0x401b4924 @duration=260, @artist=\"Fleck\", @name=\"Bicylops\"> • aSong.to_s >> "#<Song:0x401b499c>” http://ruby-doc.org/docs/ProgrammingRuby/
New improved to_s • class Song • defto_s • “Song: #{@name} -- #{ @artist } ( #{ @duration } )” • end • end • aSong = Song.new("Bicylops", "Fleck", 260) • aSong.to_s >> “Song: Bicylops--Fleck (260)” http://ruby-doc.org/docs/ProgrammingRuby/
Inheritance • class KaraokeSong < Song • def initialize(name, artist, duration, lyrics) • super(name, artist, duration) • @lyrics = lyrics • end • End • aSong = KaraokeSong.new("My Way", "Sinatra", 225, "And now, the...") • aSong.to_s … http://ruby-doc.org/docs/ProgrammingRuby/
overriding to_s • class KarokeSong • defto_s • “KS: #{@name} -- #{ @artist } ( #{ @duration } ) [#{@lyrics}]” • end • end • class KaraokeSong < Song • defto_s • super + " [#{@lyrics}]“ • end • end http://ruby-doc.org/docs/ProgrammingRuby/
Accessing instance variables • Class Song • attr_reader :name, :artist, :duration • attr_writer :duration • … • end http://ruby-doc.org/docs/ProgrammingRuby/
class JavaSong { // Java code • private Duration myDuration; • public void setDuration(Duration newDuration) { • myDuration = newDuration; • } • } • class Song • attr_writer :duration • end • aSong = Song.new("Bicylops", "Fleck", 260) aSong.duration = 257 http://ruby-doc.org/docs/ProgrammingRuby/
class Song • @@plays = 0 • def initialize(name, artist, duration) • @name = name • @artist = artist • @duration = duration • @plays = 0 • end • def play • @plays += 1 • @@plays += 1 • "song: #@plays plays. Total #@@plays plays." • end http://ruby-doc.org/docs/ProgrammingRuby/
Containers, Blocks, and Iterators • Containers • Arrays • Hashes • Implementing a SongListContainer • Blocks and Iterators • Implementing Iterators • Ruby Compared with C++ and Java • Blocks for Transactions • Blocks Can Be Closures
Containers • Hashes • h = { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' • } • h.length » 3 • h['cow'] = 'bovine' • h['cat'] = 99 • Arrays • a = [ 3.14159, "pie", 99 ] • a.type » Array • a.length » 3 • a[2] » 99 • 50 or so methods http://www.ruby-doc.org/core-2.1.0/Array.html
Implementing a SongList Container • append( aSong ) » list • Append the given song to the list. • deleteFirst() » aSong • Remove the first song from the list, returning that song. • deleteLast() » aSong • Remove the last song from the list, returning that song. • [ anIndex } » aSong • Return the song identified by anIndex, which may be an integer index or a song title. http://ruby-doc.org/docs/ProgrammingRuby/
SongList: Initializer & append • # Initializer • classSongList • definitialize • @songs = Array.new • end • end • #append method • class SongList • def append(aSong) • @songs.push(aSong) • self • end • end http://ruby-doc.org/docs/ProgrammingRuby/
SongList: Using Array methods • class SongList • defdeleteFirst • @songs.shift • end • defdeleteLast • @songs.pop • end • end http://ruby-doc.org/docs/ProgrammingRuby/
SongList: [ ] method 1rst version • class SongList • def[ ](key) • ifkey.kind_of?(Integer) • @songs[key] • else • #... • end • end • end
Class Variables • class Song @@plays = 0 • def initialize(name, artist, duration) • @name = name • @artist = artist • @duration = duration • @plays = 0 • end • defplay • @plays += 1 • @@plays += 1 • "This song: #@plays plays. Total #@@plays plays. • end • end
Class Methods • class Example • definstMeth # instance method • … • end • defExample.classMeth # class method • … • end • end http://ruby-doc.org/docs/ProgrammingRuby/
Singletons • class Logger • private_class_method :new • @@logger = nil • defLogger.create • @@logger = new unless @@logger • @@logger • end • end http://ruby-doc.org/docs/ProgrammingRuby/
Access Control • “Public methods can be called by anyone---there is no access control. Methods are public by default (except for initialize, which is always private). • Protected methods can be invoked only by objects of the defining class and its subclasses. Access is kept within the family. • Private methods cannot be called with an explicit receiver. Because you cannot specify an object when using them, private methods can be called only in the defining class and by direct descendents within that same object.” http://ruby-doc.org/docs/ProgrammingRuby/
Specifying Access • class MyClass • def method1 # default is 'public' • #... • end • protected # subsequent methods will be 'protected' • def method2 # will be 'protected' • #... • end • private # subsequent methods will be 'private' • def method3 # will be 'private' • #... • end • public # subsequent methods will be 'public' • def method4 # and this will be 'public' • #... • end • end http://ruby-doc.org/docs/ProgrammingRuby/
Blocks • a = %w( ant bee cat dog elk ) # create an array • a.each { |animal| puts animal } # iterate over the contents • Yield – will be discussed next time • [ 'cat', 'dog', 'horse' ].each do |animal| • print animal, " -- " http://ruby-doc.org/docs/ProgrammingRuby/
{ puts "Hello" } # this is a block • do # • club.enroll(person) # and so is this • person.socialize • end http://ruby-doc.org/docs/ProgrammingRuby/
Blocks • 5.times { print "*" } • 3.upto(6) {|i| print i } • ('a'..'e').each {|char| print char } • *****3456abcde http://ruby-doc.org/docs/ProgrammingRuby/
the [ ] method • class SongList • def [](key) • if key.kind_of?(Integer) • return @songs[key] • else • for i in 0...@songs.length • return @songs[i] if key == @songs[i].name • end • end • return nil • end • end
the [ ] method version 2 • class SongList • def [](key) • if key.kind_of?(Integer) • result = @songs[key] • else • result = @songs.find { |aSong| key == aSong.name } end • return result • end • end
the [ ] method version 3 • class SongList • def [](key) • return @songs[key] if key.kind_of?(Integer) • return @songs.find { |aSong| aSong.name == key } • end • end
Implementing Iterators • defcallBlock • yield • yield • end • callBlock { puts "In the block" } • Produces • In the block • In the block http://ruby-doc.org/docs/ProgrammingRuby/
deffibUpTo(max) • i1, i2 = 1, 1 # parallel assignment • while i1 <= max • yield i1 • i1, i2 = i2, i1+i2 • end • end • fibUpTo(1000) { |f| print f, " " } • produces 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
class Array • def find • fori in 0...size • value = self[i] • return value if yield(value) • end • return nil • end • end • [1, 3, 5, 7, 9].find {|v| v*v > 30 } >> 7
[ 1, 3, 5 ].each { |i| puts i } >> 1 3 5 • ["H", "A", "L"].collect { |x| x.succ } • » • ["I", "B", "M"]
Blocks for Transactions • class File • defFile.openAndProcess(*args) • f = File.open(*args) • yield f • f.close() • end • end • File.openAndProcess("testfile", "r") do |aFile| • print while aFile.gets • end
class File • defFile.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
Blocks Can Be Closures • bStart = Button.new("Start") • bPause = Button.new("Pause") • class StartButton < Button • def initialize • super("Start") # invoke Button's initialize • end • defbuttonPressed • # do start actions... • end • end • bStart = StartButton.new
class JukeboxButton < Button • def initialize(label, &action) • super(label) • @action = action • end • defbuttonPressed • @action.call(self) • end • end • bStart = JukeboxButton.new("Start") { songList.start } • bPause = JukeboxButton.new("Pause") { songList.pause }
defnTimes(aThing) • returnproc { |n| aThing * n } • end • p1 = nTimes(23) • p1.call(3) »69 • p1.call(4) »92 • p2 = nTimes("Hello ") • p2.call(3) »"Hello HelloHello "