Update: Fixed bonehead misunderstanding on my part, thanks to Daniel spotting it, and a typo thanks to riffraff.
I left a few loose ends from Part 1, so I’m moving a discussion on the type system to Part 3 so I can revisit methods and classes.
Returning from methods
In the normal way, you can return from a method using the return
keyword:
[ruby]
def calculate_sum(a, b)
return a + b
end
[/ruby]
By default however, the return value of any ruby method will be the result of the last line of execution, so the above method could be written as:
[ruby]
def calculate_sum(a, b)
a + b
end
[/ruby]
Personally, I prefer to use explicit return
calls as it reduces ambiquity as to how a method should be used.
Class and Instance variables
Last time we didn’t talk about instance variables. Unlike Java, you have no need to define instance variables before you use them. Instead, when you need one, use it with the @
prefix, like so:
[ruby]
def initialize(name)
@name = name
end
[/ruby]
To define class variables (the equivilent of Java static variables) you use two @
symbols:
[ruby]
def initialize(name)
@name = name
@@last_creation_time = DateTime.now
end
[/ruby]
Variables without the @
prefix are considered local variables, and are only available within the scope of the block they were defined in.
unless
As I showed before, you can construct simple if/elsif/else
blocks like so:
[ruby]
if some_value = = 0
…
elsif some_value = = 1
…
else
…
end
[/ruby]
Like Java, you can use !
to negate a boolean expression, or you can use !=
to denote not-equals. Ruby also adds the unless
keyword – so rather than:
[ruby]
if some_value != 0
…
end
[/ruby]
You can write the following instead:
[ruby]
unless some_value = = 0
…
end
[/ruby]
Use of unless
can help make code more readable, especially when using methods with a ?
suffix, as we’ll show in the next section.
Special Method Suffixes
Ruby allows the use of two special suffixes for method names – ?
and !
. Any method followed by a ?
is assumed to have a boolean return type, for example:
[ruby]
if task.completed?
…
end
[/ruby]
And rather than the ugly !task.completed?
:
[ruby]
unless task.completed?
…
end
[/ruby]
The second suffix is used to denote destrcutive methods – that is those methods which affect the target of the method. For example, imagine we have a Sqaure
class, which has two methods, flipHorizontal
and flipHorizontal!
– the first method should define a non-desctructive call which returns a copy of the Sqaure, whereas the second form should rotate the object itself.
Operators
In Java, operators such as +, -, *
and the like all have meanings defined in the language itself. You can use +
to concat strings, or you can use it for normal arithmetic, but that is about it. In Ruby, you can define the behaviour of these operators for each class. You’ll find yourself using this often when defining comparison operators. In Java, you’d implement the Comparable
interface, which defines compareTo
– returning -1, 0 or +1 if the object was less than, the same as or more than some other object. You would also have to seperately define equals()
for equality, and the definition of ==
always asserts object identity. In Ruby, you can implement the <=>
operator, which does the same job as Java’s Comparable
, except that it can be used as an operator. For example if we wanted to define comparison in terms of a classes name
:
[ruby]
def (rhs)
return name rhs.name
end
[/ruby]
And we could then do:
[ruby]
some_object some_other_object
[/ruby]
Include the Comparable
module in your code however, and you automatically get the <, <=, = =>, >
operators for free, as they can all be defined in terms of the result of the <=>
operator. The fun doesn’t stop there – you can also define the []
oeprator to provide array indexing of your objects:
[ruby]
class RecordCollection
def [] (index)
return @records[index]
end
end
[/ruby]
And you can even define []=
to provide a way to assign arrays:
[ruby]
def []= (array)
logger.debug(“Taking array #{array}”)
@records = array
end
…
collection = RecordCollection.new
collection[] = [Record.new(“Some Record”), Record.new(“Some other Record”)]
collection0 => Record.new(“Some Record”)
collection1 => Record.new(“Some other Record”)
[/ruby]
In Part three we’ll finally look at the Ruby typing system, and might have time to look at arrays and hashes.
6 Responses to “Ruby For Java (and C#) Programmers, Part 2 – Operators, methods, and more on classes”
“The use of the ? suffix is not simply something to make the code more readable – if you don’t specify the ? suffix your methods will return either 1 or 0, both of which equate to true in the ruby world.”
Not true.
# perfectly legal
def hello?
return “hello”
end
The “?” and “!” are a convention. There is no builtin enforcement of any kind. Of course, violating this convention is a short path to a slew of nasty emails, but I digress.
– Dan
Agh – forgot to rewrite that section before I published – thanks for picking that up Daniel.
Version 8.01
Build 7583
Platform Win32
System Windows XP
This was a post from opera.. so i guess its either fixed or it was a problem with opera.
Nice ones Sam,
One topic that I think could be interesting for a future blog in the same series would be collections (Hash, Enumerable and Array) and how they compare with their Java counterparts.
Especially how to iterate over them, insert and access values, and also how to use the very powerful join, collect, inject, each methods (these are my favourites, there are many more)
I’ll probaby introduce arrays and hashes in part three, but will save the juicy stuff for part 4. Oh, and I’ll try and grab a copy of Opera this weekend and give the site the once over.
I guess you typoed “comparable”, it should be uppercased since it is a module.
I also think it should be highlighted how mixins+operator ovwerloading in this particular case avoid code duplication and possible errors in respect to java, i.e.
a < b
instead of
a.compareTo(b)== -1