답변:
문제는 메소드를 실행할 때마다 상수에 새로운 값을 할당한다는 것입니다. 상수가 일정하지 않기 때문에 허용되지 않습니다. 문자열 의 내용 이 동일 하더라도 (어쨌든) 실제 문자열 객체 자체는 메소드가 호출 될 때마다 다릅니다. 예를 들면 다음과 같습니다.
def foo
p "bar".object_id
end
foo #=> 15779172
foo #=> 15779112
아마도 메소드에서 상수 값을 변경하려는 유스 케이스를 설명했다면 더 나은 구현을 도울 수 있습니다.
아마도 클래스에 인스턴스 변수가 있습니까?
class MyClass
class << self
attr_accessor :my_constant
end
def my_method
self.class.my_constant = "blah"
end
end
p MyClass.my_constant #=> nil
MyClass.new.my_method
p MyClass.my_constant #=> "blah"
메소드에서 상수의 값 을 정말로 변경하고 상수가 문자열 또는 배열 인 경우, '속임수'를 사용하여 #replace
실제로 오브젝트를 변경하지 않고 오브젝트가 새로운 값을 갖도록 할 수 있습니다 .
class MyClass
BAR = "blah"
def cheat(new_bar)
BAR.replace new_bar
end
end
p MyClass::BAR #=> "blah"
MyClass.new.cheat "whee"
p MyClass::BAR #=> "whee"
def initialize(db,user,password) DB=Sequel.connect("postgres://#{user}:#{password}@localhost/#{db}") end
입니다. Ruby가 간단한 방법이없는 경우 중 하나입니다.
@variable
상수가 아닌 인스턴스 변수 (예 :)를 원합니다 . 그렇지 않으면 DB
해당 클래스의 새 인스턴스를 인스턴스화 할 때마다 다시 할당 됩니다.
Sequel.connect
상수 DB 에 할당해야한다고 말하는 것은 아무것도 없다. . 실제로, 설명서에는 이것이 단지 권장 사항이라고 명시되어 있습니다. 그것은 나에게 외부 제약처럼 들리지 않습니다.
Ruby의 상수는 변경되지 않기 때문에 Ruby는 내부 메소드와 같이 두 번 이상 실행될 수있는 코드의 일부로 할당하지 않는 것이 좋습니다.
정상적인 상황에서는 클래스 자체 내부에 상수를 정의해야합니다.
class MyClass
MY_CONSTANT = "foo"
end
MyClass::MY_CONSTANT #=> "foo"
어떤 이유로 메소드 내부에 상수를 정의해야하지만 (아마도 일부 메타 프로그래밍 유형의 경우) 다음을 사용할 수 있습니다 const_set
.
class MyClass
def my_method
self.class.const_set(:MY_CONSTANT, "foo")
end
end
MyClass::MY_CONSTANT
#=> NameError: uninitialized constant MyClass::MY_CONSTANT
MyClass.new.my_method
MyClass::MY_CONSTANT #=> "foo"
다시 말하지만, const_set
정상적인 상황에서 실제로 의존 해야하는 것은 아닙니다. 이 방법으로 상수 를 실제로 할당 할지 확실하지 않은 경우 다음 대안 중 하나를 고려할 수 있습니다.
클래스 변수는 여러 가지 방식으로 상수처럼 동작합니다. 클래스의 속성이며 정의 된 클래스의 하위 클래스에서 액세스 할 수 있습니다.
차이점은 클래스 변수는 수정 가능해야하기 때문에 문제없이 내부 메서드에 할당 할 수 있다는 것입니다.
class MyClass
def self.my_class_variable
@@my_class_variable
end
def my_method
@@my_class_variable = "foo"
end
end
class SubClass < MyClass
end
MyClass.my_class_variable
#=> NameError: uninitialized class variable @@my_class_variable in MyClass
SubClass.my_class_variable
#=> NameError: uninitialized class variable @@my_class_variable in MyClass
MyClass.new.my_method
MyClass.my_class_variable #=> "foo"
SubClass.my_class_variable #=> "foo"
클래스 속성은 일종의 "클래스의 인스턴스 변수"입니다. 그것들은 값이 서브 클래스와 공유되지 않는다는 것을 제외하고는 클래스 변수와 약간 유사하게 작동합니다.
class MyClass
class << self
attr_accessor :my_class_attribute
end
def my_method
self.class.my_class_attribute = "blah"
end
end
class SubClass < MyClass
end
MyClass.my_class_attribute #=> nil
SubClass.my_class_attribute #=> nil
MyClass.new.my_method
MyClass.my_class_attribute #=> "blah"
SubClass.my_class_attribute #=> nil
SubClass.new.my_method
SubClass.my_class_attribute #=> "blah"
그리고 완전성을 위해 언급해야 할 것입니다. 클래스가 인스턴스화 된 후에 만 결정할 수있는 값을 할당 해야하는 경우 실제로 오래된 인스턴스 변수를 찾을 가능성이 큽니다.
class MyClass
attr_accessor :instance_variable
def my_method
@instance_variable = "blah"
end
end
my_object = MyClass.new
my_object.instance_variable #=> nil
my_object.my_method
my_object.instance_variable #=> "blah"
MyClass.new.instance_variable #=> nil
Ruby에서 이름이 대문자로 시작하는 변수는 상수이며 한 번만 지정할 수 있습니다. 다음 대안 중 하나를 선택하십시오.
class MyClass
MYCONSTANT = "blah"
def mymethod
MYCONSTANT
end
end
class MyClass
def mymethod
my_constant = "blah"
end
end
루비의 상수는 메소드 내에서 정의 할 수 없습니다. 예를 들어이 페이지 하단의 참고 사항을 참조하십시오
"배열 또는 해시의 내용을 대체 할 수있는"배열 (및 해시) 방법 #replace에 대해 상기시켜 준 Dorian과 Phrogz에게 감사드립니다.
CONSTANT의 값은 변경 될 수 있지만 성가신 경고와 함께 루비의 몇 가지 개념적인 실수 중 하나입니다. 이는 완전히 불변이거나 끊임없는 아이디어를 완전히 버려야합니다. 코더의 관점에서 볼 때 상수는 선언적이고 의도적이며 "이 값은 일단 선언 / 할당되면 실제로 변경할 수 없습니다"라는 신호를 보냅니다.
그러나 때때로 "분명한 선언"은 실제로 다른 미래의 유용한 기회를 예견합니다. 예를 들어 ...
가 있습니다 예를 들어, REPL 같은 메시지 루프에서 다시 로딩 ARGV는 다음 이상 (연속) OptionParser.parse 통해 ARGV를 다시 실행하십시오 "일정의"값이 정말 변경해야 할 수도 있습니다 합법적 인 사용 사례! 전화-짜잔! "명령 줄 인수"에 완전히 새로운 동적 유틸리티를 제공합니다.
실제적인 문제는 중 , "ARGV는 일정해야"한다는 추정 가정하에 또는 optparse의 자신의 초기화 방법에있는 하드 코드 후속 처리의 인스턴스 var에 @default_argv에 ARGV의 할당 - 정말 배열 (ARGV) 적절한 경우 재분석 및 재사용을 장려하는 매개 변수 여야합니다. 적절한 기본값 (예 : ARGV)으로 적절한 매개 변수화를 수행하면 "일정한"ARGV를 변경할 필요가 없습니다. 단지 2 ¢-생각의 생각 ...