开发者

Why line inside a class but outside the methods can be executed in Ruby?

Is it an intended design philosophy? For example if I have a class "Greeter" defined as follow:

1: class Greeter
2:   def say_hello
3:     puts "Hello"
4:   end
5: 
6:   puts "Goodbye!"
7: 
8: end

When I execute the file:

$ ruby greeter.rb
Goodbye!
$

In other languages (e.g. Java, PHP) I will get an error about line 6 is invalid. Rub开发者_运维知识库y's way is somehow different to what I know about OOP, or is it me misunderstand the OOP concept?


I don't understand what this has to do OOP. OOP is all about message sends, and puts "Goodbye!" is a message send. It sends the message :puts with the single argument "Goodbye!" to self.

Indeed, the thing that's not OOP is line 2, which you don't seem to have a problem with, since line 2 is not a message send.

Let's look at it from the opposite view: If the content of a class body were not executed, then how would you define methods? You are obviously not surprised that line 2 gets executed, so why should line 6 be treated any different? That would be horribly inconsistent!


It is an intended design phiolosophy. It comes from:

Is there any better place to implement and invoke class-definition logic than the class body?!


This isn't because it's object-oriented, but because of how Ruby implements OO. That "class" you're defining there…it's an object. It's an object of the type "Class". Your call to puts is considered a "class macro". The scope it is run in is the instance of the Class (not an instance of Greeter). Since Ruby creates an instance of the class definition (so a Class object) when it interprets it, your statement is run immediately at runtime.

You would do well to get a copy of the pickaxe ruby book (Programming Ruby 1.9), and if you're interested in how Ruby works with dynamic stuff like this you might really enjoy Metaprogramming Ruby as well.


Code inside a class definition, but outside any of the methods is a very powerful feature in Ruby, especially considering its dynamic nature. It is actually similar to creating static constructors in other languages. Basically, this is meant for code that should be executed before the methods on your class are ever used. You can use this to actually manipulate your class at runtime. Take a look at methods like attr_accessor to see why this is so useful.


Another way to explain it is:

class Greeter

You have executed a class statement. It defines a class and you are inside that class

2:   def say_hello
3:     puts "Hello"
4:   end

You execute a def a code inside class Greater. This code has created a method

6:   puts "Goodbye!"

You are inside class Greeter an another code (a puts) is executed. This code has printed GoodBye! in the console.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜