Java 개발자가 알아야 할 10가지
RUBY-DOC.ORG의 “10 Things Every Java Programmer Should Know About Ruby”를 번역한 문서입니다.
Ruby는 OOP이기 때문에 Java 개발자는 매우 익숙하게 다가갈 수 있다. 하지만 Java 스타일로 Ruby 프로그래밍을 하려고 하면 Ruby가 줄 수 있는 많은 가능성을 놓치기 쉽다.
생각과 행동은 사용하는 언어에 의해 영향을 받게 된다. 이 글은 “Ruby가 Java 보다 우수하다”라는 주장의 글이 아니라, Java 개발자가 Java 스타일로 Ruby 프로그래밍하는 것을 피해서 Ruby 방식으로 프래그래밍하는 방법을 발견할 수 있게 해주기 위한 글이다.
프로그래밍에 대해서 생각하는 방식에 영향을 주지 않는 언어는 배울 가치가 없다 ? Alan Perlis
Item #10 Ruby의 규약(Convention)을 익혀라
- ClassNames (클래스명)
- method_names and variable_names (메소드명이나 변수명)
- methods_asking_a_question? (질문형 메소드는 물음표 사용)
- slightly_dangerous_methods! (중요한 메소드는 느낌표 사용)
- @instance_variables (클래스 멤버 변수)
- $global_variables (static 변수)
- SOME_CONSTANTS or OtherConstants (상수)
Item #9 모든 것은 객체(Object)다
- 클래스는 객체다!
Array는 배열 클래스 객체의 이름이다.
새로운 객체를 생성하기 위해서는 특별한 문법을 사용할 필요 없이, 클래스 객체에 new 를 보내면 된다.
a = Array.new
클래스는 자신의 인스턴스를 만들 수 있기 때문에, 자체로 완전한 팩토리 객체다.
def create_from_factory(factory) factory.new end obj = create_from_factory(Array)
0.zero? # => true
1.zero? # => false
1.abs # => 1
-1.abs # => 1
1.methods # => list of methods for object 1
2.+(3) # => 5 (same as 2+3)
10.class # => Fixnum
(10**100).class
# => Bignum
a = nil a.nil? # => true a.methods # => list of methods a.abs # => NoMethodError
Java에서 null은 객체가 아니다. method 사용 불가. 참고
변수명은 객체가 아니다
블럭은 객체가 아니다.
Item #8 (거의) 모든 것은 메시지다
- 이름을 객체에 묶는다. Binding names to objects (assignment)
- 구조나 연산자를 조절한다. Primitive controls structures (e.g. if/else, while) and operators (e.g. defined?)
- 객체에 메시지를 보낸다. Sending messages to objects
string.index("x")
Send :index (with argument "x")
string.length
Send :length (with no argument)
run_status_reports
Send :run_status_reports (to self)
1 + 2
Send :+ (with argument 2) to the object 1
array[i]
Send :[] (with argument i) to the array
Ruby 프로그래머는 obj.mothod를 객체에 메시지를 보내는 것으로 생각하는 경향이 있다.
Java 프로그래머는 obj.method를 객체에서 메소드를 찾아서 그것을 호출하는 것으로 생각하는 경향이 있다.
이 미묘한 차이는 매우 중요하다. 다음 클래스를 보면, 보내지는 모든 메시지를 저장했다가 그 메시지를 다른 객체에 보내는 클래스를 정의하고 있다.
class VCR
def initialize
@messages = []
end
def method_missing(method, *args, &block)
@messages << [method, args, block]
end
def play_back_to(obj)
@messages.each do |method, args, block|
obj.send(method, *args, &block)
end
end
end
vcr = VCR.new
vcr.sub!(/Java/) { "Ruby" }
vcr.upcase!
vcr[11,5] = "Universe"
vcr << "!"
string = "Hello Java World"
puts string
# => Hello Java World
vcr.play_back_to(string)
puts string
# => HELLO RUBY Universe!
- Remote Proxies – 원격 객체에 메시지를 자동적으로 보내준다.
- Auto Loaders – 첫번째 메시지가 올때까지 기다린 후, 메시지를 로드한 후 일반적인 프록시처럼 행동한다.
- Decorators – 원하는 메시지는 가로채고 나머지는 통과시킨다.
- Mock Objects – 흉내(mock)낼 메소드를 작성한 후 나머지는 필요에 따라 위임하거나 무시한다.
- Builders – 빌더에 호출된 메소드에 따라 XML/HTML/등등을 생성한다.
Item #7 Ruby는 매우 동적이다
- Java는 C++ 보다 동적인 언어다. 하지만 Ruby는 Java보다 몇 단계 더 동적이다.
- method_missing
위의 VCR 클래스 참고
- 쉬운 리플랙션(Reflection)
[Java Code]
public static Object create(Class c, String value)
throws Exception
{
Constructor ctor = c.getConstructor(
new Class[] { String.class } );
return ctor.newInstance(
new Object[] { "Hello" } );
}
public static void main (String args[])
throws Exception
{
Greeting g =
(Greeting) create(Greeting.class, "Hello");
g.show();
}
[Ruby Code]
def create(klass, value) klass.new(value) end g = create(Greeting, "Hello") g.show
- 열린 클래스
언제든지 클래스에 메소드를 추가할 수 있따. 심지어 빌트인 클래스에도 추가할 수 있다.
class Integer
def even?
(self % 2) == 0
end
end
p (1..10).select { |n| n.even? }
# => [2, 4, 6, 8, 10]
- 싱글턴 객체
싱글턴 메소드는 클래스가 아닌 개별 객체에 정의될 수 있다.
class Dog end rover = Dog.new fido = Dog.new def rover.speak puts "Red Rover" end rover.speak # => "Red Rover" fido.speak # => NoMethodError
- Definition Hooks
갈고리(Hook)는 사용자가 프로그램 실행 도중 특정 시점에 컨트롤을 가질 수 있게 해준다.
class MyClass
def MyClass.method_added(name)
puts "Adding Method #{name}"
end
def new_method
# Yada yada yada
end
end
# => Adding Method new_method
- 코드 평가
class Module
def trace_attr(sym)
self.module_eval %{
def #{sym}
printf "Accessing %s with value %s\n",
"#{sym}", @#{sym}.inspect
@#{sym}
end
}
end
end
class Dog
trace_attr :name
def initialize(string)
@name = string
end
end
Dog.new("Fido").name # => Accessing name with value "Fido"
2 Comments
slightly_dangerous_methods! 는 결과를 자신에게 적용하는 메서드입니다. ^_^;;
a=[1,2]
b=[1,2]
a = a.reverse
b.reverse!
puts a
puts b
예. 발상이 참 신선하다고 해야하나요?
느낌표가 들어가면 결과가 자신에게 반영되기 때문에 사용시 주의해야 하는 메소드 정도로 이해하면 되겠네요.