2009-10-22 27 views
1

我感興趣的人會如何得到這個工作去:Ruby操作符可以被別名嗎?

me = "this is a string" 
class << me 
    alias :old<< :<< 
    def <<(text) 
    old<<(text) 
    puts "appended #{text}" 
    end 
end 

我想,當某樣東西附加到me變量,對象將使用重新定義的方法。

如果我嘗試運行這個,我得到syntax error, unexpected ':', expecting kEND:<<

+0

OP看上去很不開心:<< – Nakilon 2013-07-01 01:17:52

回答

3

:old<<看起來像「:old<<」。試試:old,或者如果你真的想要的話,:"old<<"(但通過這個名字很有趣)。

+0

想我真的很想把它叫做':老<<'。調用它的唯一方法是使用'send'嗎? – Geo 2009-10-22 18:29:34

+1

我認爲這很愚蠢 - 爲什麼不選一個真實的名字? - 但是,'send(:「old <<」,text)'會起作用。不管怎樣,我想不出任何其他方法用這種奇怪的名稱來稱呼某些東西。 – ephemient 2009-10-22 18:34:57

+0

只是出於好奇:) – Geo 2009-10-22 18:37:33

1

問題出在:old<<。它被解釋爲:old <<,即符號:old後跟<<運算符,所以它是一個語法錯誤。也許你可以試試:"old<<"

7

符號文字中只允許使用某些字符。您正在查找:

alias :"old<<" :"<<" 
2

正如其他人已經解釋過的,問題在於old<<不是合法的Ruby標識符。你可以用技巧創建一個名稱的方法,但是你不能以正常的方式調用它,它肯定不會被識別爲操作符。

但是,到目前爲止所有的答案,雖然他們肯定已經回答了你的問題,但完全忽略了的底層問題:該方法甚至不應該有一個名字!如果它沒有名字,那麼這個名稱就是非法的問題根本就不會發生。

#!/usr/bin/env ruby 

require 'test/unit' 
require 'stringio' 
class TestOperatorDecorator < Test::Unit::TestCase 
    def setup; @old_stdout, $> = $>, (@fake_stdout = StringIO.new) end 
    def teardown; $> = @old_stdout end 

    def test_that_me_dot_append_writes_to_stdio 
    me = 'this is a string' 
    class << me 
     old_method = instance_method :<< 

     define_method :<< do |text| 
     old_method.bind(self).(text) 
     puts "appended #{text}" 
     end 
    end 

    me << 'Test' 

    assert_equal "appended Test\n", @fake_stdout.string 
    end 
end 

在這種情況下,方法永遠不會被命名的,這不僅意味着我們不必爲發明它起一個名字,這也意味着它不會污染命名空間。

0

雖然我同意thenduks和ephemient,你可以用這種方式別名操作符,然後用send來調用它,你也可以繼承類繼承。例如: -

me = "is a string" 

class << me 
    def <<(text) 
    super 
    puts "appended #{text}" 
    end 
end 

me << " bob" 
puts me #=> is a string appended bob 
相關問題