You are on page 1of 16

LESSON #2: UNDERSTANDING OBJECTS

TABLE OF CONTENTS 1. Comparing, Conditionals and Loops ............................................................................................ 2 Ruby Control Structures and Operators ............................................................................................. 2 2. The REAL Truth About Objects ..................................................................................................... 3 Classes and the Ruby Class Hierarchy ............................................................................................. 3 Object Instances, Instance Variables and Methods ........................................................................... 6 5. Lesson 2 Review Challenge ......................................................................................................... 16 Lesson 2 Review Challenge............................................................................................................ 16

Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

1. COMPARING, CONDITIONALS AND LOOPS


RUBY CONTROL STRUCTURES AND OPERATORS Programming is an art. The subtle techniques that we use give us the feeling of satisfaction and meaning behind the program in which we are building, just like an artist gets satisfaction from genius art. There are no boundaries to the types of art that we can create, granted we understand what type of art we can make and the tools we can use to create the art. For instance, some artists create art through realism, making the art seem as visually natural as possible. Other artists create art through surrealism and abstraction hence their art has a degree of independence from the real world. Although loosely coined, it is the conceptually the same with programming. When we program, we are essentially creating abstract representations of real world objects. So as programmers, we must control the way he creates his programs. Welcome to the (virtual) world of control structures! Control structures (also known as control flow) refers to the systematic order of the execution of a set of statements. Control structures, by definition, create a lexical scope when programming and regulate how properties within the scope are manipulated. A lexical scope is simply another name for the immediate local environment in the surrounding area. Another term for properties is called members, which is widely used and a conventionally valid synonym. We often use control structures to compare expressions against one another. To do this we must understand some important operators in Ruby. The = sign A single = sign is used to assign the value on the right to the object on the left. This is called the assignment operator. a = 10 test = This is a test The == sign A double == sign is used to compare the value on the right to the object on the left. This is called comparison operator, which is used in control structures. if test == This is a test print Success end The === sign A triple === sign is used to check for equality that the value on the right is the exact same object as the one on the left. This is called equality operator, which is also used in control structures. if true === true print Both are true end
Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

It is important to know that the proper control structure to use ultimately depends on the type of objects being evaluated and the programmers desired results. Control structures begin with the name of the structure and end with the end keyword. There are, however, more advanced control structures that are implemented which well discuss later. The syntax for creating basic control structures (conditional branches and loops) are shown below:

Conditional Branches Expressions or conditions that are evaluated.


if / if-else Checks if one or more conditions are met. else is an optional branch. a = 10

if a == 10 print A is 10 else print No answer end


unless The exact opposite of if. The code-block will only be executed if the expression is false. There is no elsif or elsunless. a = 10 unless a == 5 print A is 10 # This will print A is 10 because the expression a== 5 is false end if-elsif-else A three branch conditional block that can evaluate multiple conditions. a = 10 if a == 4 print A is 4 elsif a == 7 print A is 7 else print A is 10 end ternary operator The ternary operator is simply a short version of evaluating an expression and executing a code (think of it as a shorter version of the if/else statement). The syntax is:
result = (condition) ? (expression-if-true) : (expression-if-false)

Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

Read it like this. The expression on the left of the : will be ran if the result equals the condition otherwise the condition on the right of the : will be ran.
true = true ? (puts 'a') : (puts 'b') #=> prints "a"

Use this with caution as it can get hard to read if you have large code. Also ? has another use so ambiguity can be a problem in some cases. It is wise to use parenthesis for executing your code. case The case conditional is another way to write an if-elsif-else statement (with more than one elsif). An object is given a case and when a condition is met then something happens.
case a when when when else end 0..4 then puts "#{a} is less than 5" 5 then puts "#{a} equals 5" 5..10 then puts "#{a} is greater than 5" puts "unexpected value #{a}" # If a is bigger than 10 or negative.

Loops Loops are blocks of code that are consecutively executed until a condition is met.
while The code block will be executed over and over again so long as the expression evaluates true.
while <expression> # <...code block...> end # if this is true # do code

until The code block will be executed over and over again so long as the expression evaluates false. When the expression is evaluated to true the loop ends. It is the opposite of while.
until <expression> # <...code block...> end # if this is false # do code

Often times we will want to return something from a control structure or method and store that value in some variable. We use the return keyword to return the values from control structures.
if a = 5 return true end

Note: To check more than one expression at a time in a control structure use the and (&&) and or (||) operators between expressions.

Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

Lets do an exercise on control structures and comparison. 1. 2. 3. 4. Open your OS command line prompt. Navigate to the folder where you downloaded all the files folder that came with this lesson. In the command prompt type: ruby files/control_structures.rb it will print the word No Open control_structures.rb in your text editor and fix the code. Your job in this exercise is to make the program print the word Thanks by fixing the 6 problems. 5. After you have completed the exercise open files/answers/control_structures.rb for answers and explanations. control_structures.rb teaches you: Conditional branches and nested conditional statements Critical thinking and error checking break keyword

Conditional branches and nested conditional statements Programming involves loops and conditions. There is just no way around this truth. If you already come from a programming background then you understand how crucial it is to understand control structures, which is why I taught them in this lesson, even if you may have already known this. Control structures can be nested inside of each other, which is the basis of how routing in a program is handled. You must understand conditional statements and when to use the appropriate ones to have a bug free program. Critical thinking and error checking The comments provided in the files are meant to be read for clarification. Although slightly verbose, it is clear explanation of what is happening between the problems. This exercise is intended to get you to think about how youre coding (and not necessarily why youre coding.).

2. THE REAL TRUTH ABOUT OBJECTS


CLASSES AND THE RUBY CLASS HIERARCHY A very nice diagram of the current Ruby class hierarchy can be found here: http://objectgraph.rubyforge.org/neatoOG.html It is not necessary to know this diagram for now, but it explains one good concept Ive been waiting to solidify in your brain. In its strictest sense, nearly everything in Ruby is an object (and treated as such). But what is an object really? What is this abstract idea I keep mentioning? Lets look at how to make an object and why its so important in Ruby. In order to make an object we must make a class of that object. A class is set of coding instructions that defines an object and how it should be presented in your ruby program. That class definition of an object can then be instantiated (created) throughout our program and manipulated and interact with other objects within our program. Every custom built class is an instance of the Class class in the Ruby class hierarchy. Now armed with this knowledge, lets define a class and instantiate an object of that class.
Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

OBJECT INSTANCES, VARIABLES, AND METHODS


class MyNewClass #Coding instructions end

myVariable = MyNewClass.new

# an object instance of MyNewClass

To create a new class we use the class keyword followed by a whitespace the name of the class. The first letter of the class name must be capitalized. We then use the end keyword to explicitly close our class. We can then assign a variable to the class by calling that classs new method (which instantiates the initial state of an instance of that object). In our example above myVariable is an instance of MyNewClass (i.e. an object). All of the things that this class will do goes between class and end keywords. Lets look at what those things can be: Variables Local variables, instance variables, class variables, global variables Methods class methods, instance methods, inherited methods The concept of sending/receiving messages Constants Some other things we will wait on explaining

Variables Weve already defined what local variables are in Lesson 1 and we understand them pretty clearly now. A refresher is that local variables are basic containers that can be used to store a value and can only be manipulated within the scope in which it was declared inside of. A class variable can be used by a child of the its parent class (more on this much later). A global variable can be used throughout the entire program (it is not limited by scope at all. A global variable can be accessed anywhere and is seldom used). But what is an instance variable? An instance variable is a variable defined in a class that stores a value and is associated only to the current instance of the class (the variable that was assigned the new class again that particular object). Below is an example using local and instance variables and two instances of a custom Person class.
class Person attr_accessor :name def initialize(param) @name = param end end # allows @name to be read and written # Consider this the .new method w/ 1 parameter # instance variable is now equal to local variable

me = Person.new(Kadeem) you = Person.new(Your Name)


puts me.name puts you.name

# one instance object .new calls initialize method w/ 1 argument # another instance w/ 1 argument

# calls this instances name => prints Kadeem # calls this instances name => prints Your Name Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

To define an instance variable we declare a name preceded by an @ symbol. You use the same naming conventions as a local variable. In the above example @name is an instance variable. This means that every instance of a Person object that we create will have @name attribute that we can access. attr_accessor will be fairly new to you but it is extremely easy to understand. attr_accessor is a type of Ruby syntactical sugar (which is just a fancy name for a way of Ruby understanding what youre really implying). What attr_accessor means is that we want our class (Person) to have the ability to read and write to an instance variable (@name). Now we have the ability to not only access a Persons @name but we also have the ability to overwrite a Persons @name. If we only wanted to access an instance variables value (i.e. allow access to it from the outside world external access only) we declare attr_reader and if we only wanted to write to an instance variable (i.e. deny all access to it from the outside world - internal access to the class only) we declare attr_writer. In our example we want to read and write so we chose to use attr_accessor so at any time later in our program we can overwrite @name for that particular instance of that Person object. Things like variables are the called attributes of a class. They can also be used for other things which we will learn later. We will skip constants, class variables and global variables for now and save them for another day. Methods A method is a simply set of instructions inside of a class that you as a programmer define. That method can then be invoked and called upon in your program. For the sake of comprehension, a method is the same thing as a function in other languages. Most programmers argue that a method is a function defined inside of a class whereas a function is not defined in any class (perhaps floating in a main namespace). Methods are the actions and behaviors that your class will perform. Methods can be custom built and also overwritten (Yes you can manipulate the behavior of a default Ruby classs methods!). To create a method we use the def keyword followed by the name of the method (lowercase convention) and an end keyword to close it. When we create an instance (object) of our Person class we set the variable equal to Person.new. .new is a method of Rubys Class class (see Ruby hierarchy ) that calls that classs initialize method. Every class in Ruby has an initialize method. Even if we dont explicitly define the initialize method, Ruby will create one for us automatically (it will be empty of course). The purpose of the initialize method is to create the initial state of the object instance. Once the initial state of the object has been completed we have an instance of our object that is referenced by our variable (in our example me and you are the variables where we are referencing two separate instances of the Person class). Some methods are public to the entire program, but some can be private and protected (we will discuss scope and types of methods in another lesson). By default all custom methods are made public and can be accessed anywhere in the program. Methods can also have parameters associated with them. A parameter is a placeholder that is associated with an argument when the method is invoked. It is used to setup variables in a method, but has no explicit value. In our example param is a method parameter and Kadeem and Your Name are method call arguments. Parameters become local variables once an argument has been given when we call the method. Thus, our method initialize now contains a local variable called param that it can use inside of itself.
Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

Lets do two exercises on classes, objects, variables, and methods. 1. 2. 3. 4. Navigate to the folder where you downloaded all the files folder that came with this lesson. In your command prompt open: ruby files/game.rb You are going to play a fighting game with an AI computer opponent for the chance to win $1,000,000. After you have completed the game open were going to go step-by-step below to build this game.

The code behind game.rb teaches you: Creating a standalone ruby program Classes, object instances and initialization Instances variables and methods How classes can interact with each other Accessibility and scope Loops and conditional statements Interpolation A brief introduction to Array objects sample method A very brief introduction to regular expressions Creating random numbers Creating a nave system of artificial intelligence Exiting a program

Well go step by step in how to build this program. Part 1: The concepts in our game The first part is just to understand what will be in our program. We want to create a game and some fighters in the game. Armed with this knowledge we know we are going to build two separate classes. The concept of what a fighter will be goes in a Fighter class and the concept of the game itself will go in a Game class.
class Fighter # Defines a Fighter object end class Game # Defines a Game object end

Part 2: Control and characteristics of each class Now that we know the objects that our game lets identify control and some of the characteristics of classes.
Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

We want to have our Game class to be the center of control in our game. That means that our Game class will need two instances (objects) of our Fighter class and will control how those two instances interact with each other. This means that our Game class must have public access to the behaviors and attributes (sometimes called members) of the Fighter class. This public access is considered a type of class scope. Scope deals with access to the members of a class. We want our Game class to have access to everything about a Fighter class. When we start our game and create two Fighters we want to set the initial state of those Fighters. So what are some of those initial characteristics of a Fighter? Lets give our Fighter class some attributes for our game.
class Fighter attr_reader attr_reader attr_accessor attr_accessor attr_accessor :name :weapon :health :defenseless :dead # # # # # Sets Fighter name Sets Fighter weapon Sets Fighter health By default he is not defending By default he is not dead

def initialize(name, weapon) @name = name @weapon = weapon @health = 50 @defenseless = true @dead = false end

So when we create a new Fighter we initialize a name, weapon, health and statuses. To the outside world the name and weapon can only be read (and cannot be overwritten), while the health and statuses can be read and overwritten because of the scope restrictions. Next lets define some of custom behaviors of a Fighter class. These will be our Fighter public methods.
#... def attack(damage_factor) case @weapon when "Longsword" then (Random.rand(7...29) * damage_factor).to_i when "Crossbow" then (Random.rand(9...22) * damage_factor).to_i when "Hammer" then (Random.rand(1...39) * damage_factor).to_i when "Shotgun" then (Random.rand(4...22) * damage_factor).to_i end end #...

Our Fighter can attack. The damage ensued is determined by the Fighters @weapon, therefore were going to give @weapon a case statement and generate the damage by a Random number between a range of numbers multiplied by a damage_factor that is controlled by Game (and finally explicitly convert that number to an integer using .to_i). Because the randomly generated number is the last expression evaluated in the attack method, that number gets returned to the receiver of the attack method (of course this will be handled by our Game).

Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

10 #... def took_damage(amount) @health -= amount if @health <= 0 @health = 0 @dead = true end end #... # Is health less than 0? # Fighter is dead

Our Fighter can take damage from an attack. In our Game class, the receiver from the attack method (the number returned from the attack method) becomes the amount argument when the took_damage method is called. When a Fighter takes damage we want to subtract the amount from the fighters @health. We would not be able to do this if we didnt have the overwriting capabilities we specified earlier. We also want to check if that Fighters @health is now 0 or less than 0. If it is, then we set @health to 0 and change the state of the Fighter object to @dead. Our Game class will check whether a Fighter is dead at the beginning of the next turn and route the state of the game appropriately.
#... def defend @defenseless = false end #...

Our Fighter can defend against an attack. This small method simply changes the status of our Fighter object. When our opponent Fighter attacks us while @defenseless is true we will take maximum damage, but when our opponent attacks us while @defenseless is false we will only take 1/3 damage. This is the damage_factor we defined earlier. Of course, a Fighter cannot defend forever so at the beginning of the Fighters turn, we will have our Game class set @defenseless back to true every time. This decision making will controlled, of course, by the Game class.
#... def heal @health += Random.rand(1...20) if @health >= 100 @health = 100 end end end #END of Fighter class

Finally, our Fighter can heal himself. Because our Game class can access a Fighters @health we can explicitly increase @health by a random amount. We also set the Fighters @health to 100 if it ever goes over 100 (otherwise we could heal forever!). We then end our Fighter class. Thats it! Thats all we need to define our Fighter class. You just learned some important concepts about instance variables (@), scope (public and private), and some other neat things (randomly generated numbers and also Range objects). Next lets define our Game class.
Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

11

We said earlier that our Game class will control (i.e. have access to) the Fighter class. This means that our Game class will have to create two instance objects of the Fighter class (one will be us, the other will be a computer opponent). We dont want anyone to access the behaviors of our Game class, so all of the methods inside of our Game class will be private and inaccessible anywhere in our program (aside from initialize which is always public). This is an important concept because we wouldnt want to directly alter the state of the Game by calling some of its methods, we want the Game to control itself (a concept I like to call self-containment). One more thing about our Game class. For the sake of comprehension we will avoid handling Exceptions (errors) in our program for now. We will spend an entire lesson on this later. Our program wont have any bugs, but as a rule of thumb, once we cover exceptions and error handling you should implement them. Lets build our Game class. We need to be able to create and manipulate two Fighter object instances. We also need a way to store which Fighter object has the current turn. Additionally, although not required, we should specify the actions a Fighter can invoke in our Game and be able to read them (not overwrite them).
class Game attr_accessor :player1 attr_accessor :player2 attr_accessor :current_turn attr_reader :actions def initialize(player1_name, player1_weapon) @current_turn = nil @actions = ["Attack", "Defend", "Heal", "Nothing"] weapons = ["Longsword", "Crossbow", "Hammer", "Shotgun"] @player1 = Fighter.new(player1_name, player1_weapon) @player2 = Fighter.new("Bob the Grandmaster", weapons.sample) opening_sequence end

We now have the initial state of our Game. When Game.new is called, we need the name and weapon that player 1 has entered. We want our Game to be able to read @actions that a Fighter can take. We also want to store the weapons that a Fighter can choose (used for player 2 computer only). Both collections are stored in Array objects ( using [ ] braces ) respectively. We then create a new Fighter called @player1 with the player 1s name and weapon and also a @player2 object with a name of Bob the Grandmaster and a random weapon from the weapons Array collection (weapons.sample does this for us). Remember that @player1 and @player2 are now newly created object instances of our Fighter class that can be used inside our Game class. Finally after we have created our objects we call our (private) opening_sequence method of our Game.
#.. private #..

The methods below this private declaration are now internally accessible to the Game class, but inaccessible to the outside world (i.e. Fighter class cannot access these methods.). Lets start with opening_sequence.
Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

12 #... def opening_sequence puts "\nWelcome to Fight Club, #{@player1.name}!"; gets; puts "\nFight your opponent for the chance to win $1,000,000!"; gets; puts "\nPress Ctrl + C at anytime to exit the fight."; gets; puts "\nLet's flip a coin to see who goes first!"; gets; puts "\nChoose heads or tails!" choice = gets.chomp.downcase coin_toss(choice) gets; puts "\nLet's fight!"; gets; update end #...

# An

Here we have defined our games opening sequence. At this point when this method is called we have fully created our two Fighters as @player1 and @player2 objects. We print an introduction that the player will see and supply gets in intermediate lines so that the player can read the lines. We also want to space out our lines a little for readability so we need to put carriage returns. \n means newline in a string. We also use interpolation inside of our strings to access members of our object (in this case we want to access @player1s name attribute and will be printed thanks to puts). We do interpolation in a string by using a unique syntax like so: #{ stuff_goes_here }. We can put expressions, method calls, variables, classes, roughly anything inside of interpolated expressions. Next lets have our player flip a coin heads or tails to see who goes first in our game. The user input is stored in the choice local variable all lowercase. That value is then passed as an argument to the coin_toss method in our Game class which well define later. coin_toss will store the new value of our Games attribute @current_turn. Because we have set the Games @current_turn (remember we can access @current_turn anywhere in our Game class) we will then call our main Games loop update method and start our game! So lets first define coin_toss and then our update method.
#... def coin_toss(choice) if choice == "heads" puts "\nGot it! #{@player1.name}, you go first!" @current_turn = @player1 else puts "\n#{@player2.name} goes first!" @current_turn = @player2 end end #...

Here we define our coin_toss that method that has one parameter. It checks if the choice selected is heads and sets @current_turn equal to @player1 object, otherwise sets @current_turn equal to @player2 object. We didnt have to explicitly set @current_turn here; Ruby always returns the last expression evaluated in the method. We could have written the last line as @player1 or @player2 and set a @current_turn equal to the coin_toss method call in our opening_sequence. I did it like this because I like to explicitly know what my methods are really doing and their purpose which means that my coin_toss method returns nil. Either way is fine, and it is simply a matter of taste. When you begin to write your own programs you will find the best procedures for yourself. Great now we know who goes first in our game. Lets create our games main loop.
Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

13 #... def update if @current_turn.dead == true gameover(@current_turn, switch_turn) else @current_turn.defenseless = true if @current_turn === @player1 puts "\n\n\n\n#{@current_turn.name}, it's your turn." puts "\nWhat do you want to do? 1: #{@actions[0]} 2: #{@actions[1]} 3: #{@actions[2]} 4: #{@actions[3]}" choice = gets.chomp.capitalize do_action(choice) else @current_turn === @player2 puts "\n\n\n\nIt's now #{@current_turn.name}'s turn"; gets; puts do_action(@actions.sample); gets; end end end #...

This is the main loop of our program. It is a custom method called update. This loop first checks if the @current_turn (@player1 or @player2) object has a @dead attribute that is true. If it is true we call the Games gameover method with two parameters (the (losing) Fighter object, and a method call to switch_turn which returns the (winning) Fighter object). We have not defined the switch_turn method yet, but its purpose is to simply return the opposite Fighter object. So gameover will have two arguments and we will define that method a little later as well. If that @current_turns @dead attribute is set to false we reset the @current_turns @defenseless attribute back to true (since it is currently that Fighters turn and hes still alive). Then we have another condition (we call this nested conditional statements). If the @current_turn object the same as (note the === sign) @player1 we print their name and the actions in which they can perform and wait for user input and do that action by calling do_action, passing it the action choice. If the turn object is the same as @player2 we print its @name (i.e. Bob the Grandmaster). We then call do_action passing it a random action from the Games @actions. Because @player1 or @player2 has called do_action we will want our do_action method to recall update after it is done. So lets define our switch_turn method first and then our do_action afterwards.
#... def switch_turn if @current_turn === @player1 @current_turn = @player2 else @current_turn = @player1 end end #...

Here is Games switch_turn method that simply (explicitly) assigns the new @current_turn object. We have to be careful with it because we dont want to ruin the update method and state of the game. We will call the switch_turn method when necessary (before the calls to the update method throughout our program).
Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

14 #... def do_action(choice) if @current_turn === @player1 opponent = @player2 else opponent = @player1 end case choice when "Attack" then puts "\n#{@current_turn.name} is attacking #{opponent.name} with a #{@current_turn.weapon}!" if opponent.defenseless == true damage = @current_turn.attack(1.0) else damage = @current_turn.attack(0.3) end gets; puts "#{opponent.name} took #{damage} damage!" opponent.took_damage(damage) puts "#{opponent.name}'s health has dropped to: #{opponent.health}"; gets; when "Defend" then puts "\n#{@current_turn.name} is now defending against #{opponent.name}'s next attack." @current_turn.defend; gets; when "Heal" then puts "\n#{@current_turn.name} is now healing."; @current_turn.heal puts "#{@current_turn.name}'s health is now: #{@current_turn.health}"; gets; else puts "\n#{@current_turn.name} has dropped his guard and is defenseless this turn!"; gets; end switch_turn update end #...

# Up

Here is our do_action method with one parameter. It maps the either @player1s user input choice to an action or @player2s randomly selected choice from the update method. We give the choice a case and a corresponding call to the Fighter objects helper classes. If we are attacking, we grab a temporary instance of the opposite opponent and call the opposite opponents took_damage method and supply a damage_factor argument. Once the action method has been executed we call switch_turn again and recall update. As you can see, control is passed back and forth between do_action, update, and Fighters helper methods. Finally we need to define our gameover method when a Fighter is dead.

Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

15 #... def gameover(loser, winner) puts "\n#{loser.name} is dead! #{winner.name} is the winner!"; gets; if winner == @player1 puts "#{winner.name}, you have just won $1,000,000!" end puts "Thanks for playing!";gets; exit end end #END of Game class end # END Game class

The gameover method has two object parameters, the losing Fighter object and the winning Fighter object. We print the winner and if it is @player1 you win $1,000,000. We then exit the program by calling the exit command (built-in Ruby method). We have one more objective - initialize the game.
# Create a new game while true puts "Enter Your Name" player1_name = gets.chomp.capitalize if player1_name.empty? || player1_name =~ /\d/ puts "\n\nPlease enter a valid name to continue" else break end end while true puts "\nEnter your Weapon of choice: Longsword, Crossbow, Hammer, Shotgun" player1_weapon = gets.chomp.capitalize case player1_weapon when "Longsword" then break when "Crossbow" then break when "Hammer" then break when "Shotgun" then break else puts "\nSorry I'm not sure we have that weapon. Please try again." end end game = Game.new(player1_name, player1_weapon)

# As

Here we create two infinite loops that only break if player1_name and player1_weapon are valid. For player1_name we get the input and make sure it isnt empty and that it isnt a number by using a string matching principle called a regular expression (/\d/ part). We will learn more on regular expressions later. For player_1weapon the user must input with the correct string. Once they are valid we pass them to a new instance of the Game class. And there you have it. We have a standalone fighting game. The concepts of object instances and classes should be drilled in your head now. I hope you enjoyed my tutorial on objects.

Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

16

3. LESSON 2 REVIEW CHALLENGE


LESSON 2 REVIEW CHALLENGE Your challenge is to build a banking system. You can begin by defining an Account class (checking and savings) and a Bank class. Maybe the bank can lend @loans to its members? You can use your imagination with it. There is a couple of catches. One is that no Burglar should be able to access a Bank class or an Account class. The Burglar could try to rob the bank during a random time of the day and if successful (at random) he steals money from an Account! Perhaps the Bank can call the Police in the attempt of a burglary? The possibilities here are endless but bring real world situations and program them from abstract concepts with the information learned from this lesson. Whats to come in the next lesson: Rubys Secret Weapon: Blocks A Closer Look At Arithmetic The Beauty Of Arrays and Hashes Inheritance, Modules, and Mixins Instance Methods Vs. Class Methods Useful Methods Cheat Sheet

Thanks for downloading. Contact me: kadeempardue@gmail.com Downloaded from: www.soultheory.net

Resources: www.ruby-lang.org http://www.ruby-doc.org/docs/ProgrammingRuby http://apidock.com http://www.skorks.com/ http://explainruby.net/ - An online Ruby code interpreter! http://rubylearning.com/

Learn Ruby: Lesson 2 Understanding Objects www.soultheory.net

You might also like