How do Class definitions in Ruby differ from other OO languages?


#1

What do you mean when you say"Class definitions are executable code".
How do classes differ from other OO languages?


#2

kunjaan wrote:

What do you mean when you say"Class definitions are executable code".
How do classes differ from other OO languages?

Inside of the class…end you can have expressions as well as method
definitions.

class Foo
x = ARGV.size + 3 + $$ # x is a local var
define_method :bar do |y| # define a method using
x+y # a scope that includes x
end
p Foo.new.bar(100) # another expression
end

You can’t do that in C++, Java, etc.


#3

kunjaan wrote:

What do you mean when you say"Class definitions are executable code".
How do classes differ from other OO languages?

Because the class is only created when the class definition code is
actually run. For example, the following code is syntactically fine:

a = Foo.new
class Foo
def bar
end
end

However at runtime it fails at the first line, because class Foo does
not exist yet.

That example might suggest this behaviour is a bad thing, but in
practice it’s a good thing. It means, for example, you can “re-open”
classes and add new methods at runtime. (“re-open” is not an accurate
term; the class always remains open)


#4

On Tue, May 26, 2009 at 4:37 AM, Brian C. removed_email_address@domain.invalid
wrote:

kunjaan wrote:

What do you mean when you say"Class definitions are executable code".
How do classes differ from other OO languages?

Because the class is only created when the class definition code is
actually run. For example, the following code is syntactically fine:

Another difference between Ruby and many other OO languages including
Java, C++ and Smalltalk is that classes don’t define the contents of
their instances. In those languages, and many others, instance
variables/fields are declared in the class (at least their existence,
and for staticly typed languagues their type) and all instances have
exactly the set of instance variables inherited from any superclasses
plus those declared in the class itself.

In Ruby each object instance has only those instance variables which
have been initialized by whatever methods have been run with that
object as self over the course of its lifetime.

http://talklikeaduck.denhaven2.com/2008/02/08/whose-variable-is-it-anyway


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale


#5

Am Dienstag 26 Mai 2009 00:05:07 schrieb kunjaan:

What do you mean when you say"Class definitions are executable code".

It means that class definiton happens at runtime. You can have any valid
ruby
expressions inside a class body, and they will be executed as they
encountered
by the parser. Example: loops:

class Foo
(1…9).each do |i|
define_method(“add#{i}”) do |x|
x+i
end
end
end

Foo.instance_methods(false)
#=>[“add2”, “add9”, “add5”, “add1”, “add8”, “add4”, “add7”, “add3”,
“add6”]

Foo.new.add5(6)
#=> 11


#6

kunjaan wrote:

What do you mean when you say"Class definitions are executable code".
How do classes differ from other OO languages?

I like to say it like this:

Ruby doesn’t have class declarations. “Declaring” a class is actually
just constructing a new Class object and running code against it. All
classes start out blank and must have methods and instance variables
added to them at runtime.

  • Charlie

#7

Charles Oliver N. wrote:

kunjaan wrote:

What do you mean when you say"Class definitions are executable code".
How do classes differ from other OO languages?

I like to say it like this:

Ruby doesn’t have class declarations. “Declaring” a class is actually
just constructing a new Class object and running code against it. All
classes start out blank and must have methods and instance variables
added to them at runtime.

In Brand X…

class Foo

   # <----- this area can't execute statements

 method Bar
   # <----- this area can execute statements.
 end

end

In Ruby…

class Foo

   # <----- this area CAN execute statements

 def Bar
   # <----- this area can execute statements.
 end

end

A class is a block that evaluates from top to bottom, like any other
code. Some
other languages allow that too.


#8

On Wed, May 27, 2009 at 3:01 AM, Charles Oliver N.
removed_email_address@domain.invalid wrote:

at runtime.
As I tried to point out earlier in this thread, that last phrase is a
bit ambiguous.

If we’re talking about “class instance variables” then yes, Ruby
classes have instance variables added to them at runtime, but classes
don’t “know” about the set of instance variables that their INSTANCEs
have, in the same way that the do in Java or Smalltalk.

Each instance acquires instance variables only when a method is run
with that instance as self which defines the iv by initializing it.
At least this is what it must look like to the Ruby program, defined?
@iv must return nil for each instance until @iv has been defined in
THAT instance:

class Foo
attr_accessor :iv
def iv_defined?
defined? @iv
end
end

f1 = Foo.new
f2 = Foo.new

f1.iv_defined? # => nil
f2.iv_defined? # => nil
f1.iv = 1
f1.iv_defined? # => “instance-variable”
f2.iv_defined? # => nil

Implementations might play some tricks due to the underlying VM
implementation like pre-allocating slots to hold some ivs, but that
has to be hidden from the Ruby programmer. If used it needs to be one
of those VM implementation ‘cheats’ which the VM implementer needs to
avoid being caught using.

MagLev does, or maybe did, do something like this. It assigns the
first few ivs it sees to fixed slots, since the Smallalk object model
prefers fixed iv name to slot offset mappings. They had some issues
with not handling defined? properly something which the RubySpec
didn’t cover until I added that http://rubyspec.org/issues/show/82
I’m not sure exactly what changes that caused in their implementation.

I don’t know what JRuby does.

Ruby 1.8, uses a hash to implement ivs, Ruby 1.9 uses a dynamic
allocation technique which DOEs move the hash to the instance’s
immediate class, and maps iv names to slot indexes, in an array of
slots either directly inside the object’s ‘box’ for an instance with a
very small number of IVs or to a separate array, with slots
initialized to a value which represents not nil, but undefined. One
of the things that’s different in this implemenation is that in a case
like

class A
attr_accessor :a, :b
end

class B < A
end

the offset of @a might be different for instances of A than for
instances of B, i.e. the offsets are NOT inherited.


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale


#9

Rick DeNatale wrote:

I don’t know what JRuby does.

In JRuby 1.2 and prior, it was slot-based for up to 5 varables and then
a simple hashtable for anything larger.

In 1.3 and up, instance variables are all slot-based and should use less
memory as well. The implementation is similar to 1.9, except that the
instance variable slot locations are call-site cached (so subsequent
lookups to the same ivar against the same type are only a few memory
dereferences).

The new impl still passes all the same RubySpecs.

  • Charlie