2012-11-05 8 views
32

W języku Ruby istnieje sposób na "przesłonięcie" stałej w podklasie w taki sposób, że wywołanie dziedziczonej metody z podklasy powoduje, że ta metoda używa nowej stałej zamiast starej? Na przykład:W języku Ruby istnieje sposób na "przesłonięcie" stałej w podklasie, aby metody odziedziczone używały nowej stałej zamiast starej?

class SuperClass 
    CONST = "Hello, world!" 
    def self.say_hello 
    CONST 
    end 
end 

class SubClass < SuperClass 
    override_const :CONST, "Hello, Bob!" 
end 

SuperClass.say_hello # => "Hello, world!" 
SubClass.say_hello # => "Hello, Bob!" 

Jeśli nie, czy istnieje sposób, aby zamiast tego zrobić coś takiego?

class SuperClass 
    CONST = "Hello, world!" 
    def self.say_hello 
    CONST 
    end 
end 

SubClass = SuperClass.clone 
SubClass.send(:remove_const, :CONST) 
SubClass.const_set(:CONST, "Hello, Bob!") 

SubClass.say_hello # => "Hello, Bob!" 

Uwaga: Próbowałem mój drugi przykład w IRB i wydaje się pracować z tym, że metody klasy nie może wydawać się, aby uzyskać dostęp CONST po I sklonować Klasa:

irb(main):012:0> SubClass.say_hello 
NameError: uninitialized constant Class::CONST 
     from (irb):4:in `say_hello' 
     from (irb):12 
     from C:/Ruby193/bin/irb:12:in `<main>' 

Odpowiedz

49

Zrobiłem to, po prostu przedefiniowując stałą w podklasie, a następnie odnosząc się do niej metodami: self.class::CONST w metodach instancji i self::CONST w metodach klas. W twoim przykładzie:

class SuperClass 
    CONST = "Hello, world!" 
    def self.say_hello 
    self::CONST 
    end 
end 

class SubClass < SuperClass 
    CONST = "Hello, Bob!" 
end 

SubClass.say_hello #=> "Hello, Bob!" 
+2

To wydaje się świetnym sposobem na zrobienie tego. Niestety nie zadziała w mojej sytuacji, ponieważ klasa, którą chcę zastąpić stałymi, jest częścią zewnętrznej biblioteki (klejnotu), której tak naprawdę nie chcę zepsuć. – Ajedi32

+1

@ Ajedi32 Wszystkie klasy są otwarte do modyfikacji, w tym do wewnętrznej biblioteki lub zewnętrznego klejnotu. Możesz po prostu użyć 'class String/* blah blah */end' aby zmodyfikować klasę string, itp. – texasbruce

+1

@texasbruce Tak, ale w tym przypadku nie chcę modyfikować gem; Chcę tylko klona klasy wewnątrz klejnotu, który ma lekko zmodyfikowaną stałą. Nadpisywanie metod lub stałych w samej klasie mogłoby zepsuć wewnętrzne działanie klejnotu, co nie jest tym, co chcę zrobić. – Ajedi32

Powiązane problemy