2011-07-15 18 views
103
class MyClass 
    def mymethod 
    MYCONSTANT = "blah" 
    end 
end 

bana hata veriyor? Sadece bir dize atarım.Dinamik sabit atama

+25

Dynamic Constant Dry Water gibi bir şeydir? :) – fl00r

+30

Sabitin dinamik olduğunu söylemez. Ödevin dinamik olduğunu söylüyor. – sepp2k

cevap

99

Sorununuz, yöntemi her çalıştırdığınızda sabit için yeni bir değer atadığınızdır. Sabit olmayan sabit hale getirdiğinden, buna izin verilmez; dizgenin içeriği içeriği aynı olsa da (şimdilik, şimdilik), nesnesi nesnesinin kendisi, yöntemin her çağrılmasında farklıdır. Örneğin: Eğer kullanım örneğini-neden bir sabit bir değerini değiştirmek istiyorum açıkladı Belki eğer

def foo 
    p "bar".object_id 
end 

foo #=> 15779172 
foo #=> 15779112 

yönteme-biz daha iyi bir uygulama konusunda size yardımcı olabilir.

Belki de sınıfta bir örnek değişkeni olmasını mı tercih edersiniz?

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" 

Eğer gerçekten bir yöntemde sabit değerini değiştirmek istiyorum, ve sabit almaya nesneyi neden bir dize veya bir dizi, sen 'dolandırıcı' ve #replace yöntemi kullanabilirsiniz ise aslında nesneyi değiştirmeden yeni bir değer tarih: Ruby

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" 
+18

OP hiçbir zaman sabitin değerini değiştirmek istediğini, ancak sadece bir değer atamak istediğini söylemedi. Bu Ruby hatasına neden olan sık kullanım durumu, değeri, diğer çalışma zamanı öğelerinden (değişkenler, komut satırı argümanları, ENV), tipik olarak bir kurucuda, örneğin bir yöntemde oluşturduğunuz zaman olur. def başlatılır (db, kullanıcı, şifre) DB = Sequel.connect ("postgres: // # {user}: # {password} @ localhost/# {db}") sonu. Ruby'nin basit bir yolunun olmadığı vakalardan biri. –

+1

@ArnaudMeuret Bu durumda, bir örnek değişkeni (örneğin, '@' değişkeni), sabit değil. Aksi takdirde, bu sınıfın yeni bir örneğini her başlattığınızda 'DB' yeniden atayacaktır. – Ajedi32

+2

@ Ajedi32 Bu durum genellikle, Sequel ile yaptığım örnek gibi tasarım seçeneklerinin değil, dış kısıtlamalardan kaynaklanır. Benim amacım, bir sabite bir değer atamanın Ruby tarafından belirli kapsamlarda ve başkalarına izin verilmemesidir. Ödevi gerçekleştirirken akıllıca seçmek için geliştiriciye kalmıştı. Ruby bu konuda değişti. Herkesin iyiliği için değil. –

19

, adını büyük harfle başlayan herhangi değişken bir sabittir ve sadece bir kez kendisine atayabilirsiniz. bu alternatiflerden birini seçin:

Ruby sabitler değiştirilemez anlamına gelmez Çünkü
class MyClass 
    MYCONSTANT = "blah" 

    def mymethod 
    MYCONSTANT 
    end 
end 

class MyClass 
    def mymethod 
    my_constant = "blah" 
    end 
end 
56

, Yakut böyle iç yöntemleri gibi bir kereden fazla idam olabilir kod parçaları, kendilerine tahsis sizi teşvik etmemektedir. Eğer gerçekten (belki metaprogramlama bazı türü için) bir yöntem içinde bir sabit tanımlamak gerekiyor olsa da, varsa nedense

class MyClass 
    MY_CONSTANT = "foo" 
end 

MyClass::MY_CONSTANT #=> "foo" 

:

Normal şartlar altında, sınıfın kendi içinde sabit tanımlamalıdır Eğer const_set kullanabilirsiniz:

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" 

Yine de, const_set normal şartlar altında gerçekten başvurmak zorunda gereken bir şey değildir. Eğer gerçekten bu şekilde sabitleri için atama olmak isteyip emin değilseniz, aşağıdaki alternatiflerden birini göz önünde bulundurmak isteyebilirsiniz:

Sınıf değişkenleri birçok yönden sabitleri gibi davranmaya

Sınıf değişkenleri. Bir sınıftaki özelliklerdir ve tanımlandıkları sınıfın alt sınıflarında erişilebilirler.

Buradaki fark, sınıf değişkenlerinin değiştirilebilir olması ve bu sayede sorun yaşanmadan içsel yöntemlere atanabilmesidir.

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" 

Sınıf

Sınıf nitelikleri "bir sınıf üzerinde örnek değişkeni" bir tür vardır bağlıyor. Değerleri alt sınıflarla paylaşılmadığı sürece sınıf değişkenleri gibi davranırlar.

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" 

örnek değişkenleri

Ve sadece şeyiyle ben muhtemelen belirtmeliyim: Eğer sınıf örneği edildikten sonra sadece belirlenebilir bir değer atamak gerekirse, aslında arıyor olabilir iyi bir şans var eski bir eski örnek değişken için.

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 
+0

Bu en net cevaptır. – Snowcrash

+0

'const_set' doğru cevaptır. – robbie613

0

Sen büyük harflerle bir değişken ismi olamaz ya Yakut bu durumda o değeri bir hata, bir "dinamik sabit atama hatası olacağını var değişen, onun bir sabit asume edecek ve buna değer sabit olduğunu tutmak isteyeceksiniz ". Küçük harfle birlikte olmalı

class MyClass 
    def mymethod 
    myconstant = "blah" 
    end 
end