2012-02-14 18 views
14

Tengo una clase personalizada y quiero poder anular el operador de asignación. Aquí se muestra un ejemplo:Método setter (asignación) con múltiples argumentos

class MyArray < Array 
    attr_accessor :direction 
    def initialize 
    @direction = :forward 
    end 
end 
class History 
    def initialize 
    @strategy = MyArray.new 
    end 
    def strategy=(strategy, direction = :forward) 
    @strategy << strategy 
    @strategy.direction = direction 
    end 
end 

este momento, no funciona según lo previsto. en el uso de

h = History.new 
h.strategy = :mystrategy, :backward 

[:mystrategy, :backward] se asigna a la variable de la estrategia y la dirección de la variable permanece :forward.
La parte importante es que quiero poder asignar un valor estándar al parámetro de dirección.

Cualquier pista para hacer este trabajo es muy apreciada.

Respuesta

14

Debido a que el azúcar sintaxis de los métodos cuyos nombres terminan en =, la única manera de que realmente puede pasar múltiples parámetros al método es evitar el azúcar sintaxis y el uso de send ...

h.send(:strategy=, :mystrategy, :backward) 

... en el cual caso puede ser que también acaba de utilizar un método normal con mejores nombres:

h.set_strategy :mystrategy, :backward 

Sin embargo, usted podría reescribir su método para automáticamente un-array los valores si sabía que una matriz no es legal para el parámetro:

def strategy=(value) 
    if value.is_a?(Array) 
    @strategy << value.first 
    @strategy.direction = value.last 
    else 
    @strategy = value 
    end 
end 

Esto parece como un corte bruto a mí, sin embargo. Utilizaría un nombre de método sin asignación con múltiples argumentos si los necesita.


Una sugerencia alternativa: si las únicas direcciones son :forward:backward y ¿qué pasa con:

def forward_strategy=(name) 
    @strategy << name 
    @strategy.direction = :forward 
end 

def reverse_strategy=(name) 
    @strategy << name 
    @strategy.direction = :backward 
end 
+0

Editado para agregar otra sugerencia para una implementación alternativa. – Phrogz

+0

Me gusta la sugerencia donde se comprueba si el valor es una matriz. Usted dice que es un hack bruto. ¿Dónde usar esto causaría problemas? – FlyingFoX

+1

@FlyingFoX Es un "hack bruto" en la medida en que no es idiomático, no es auto-documentado y no es generalmente aplicable (en el caso en que alguien quiera pasar una matriz como primer parámetro). – Phrogz

2

El problema es

def strategy=(strategy, direction = :forward) 
    @strategy = strategy 
    @strategy.direction = direction 
end 

Al configurar

h.strategy = :mystrategy, :backward 

en realidad está anulando la instancia original @strategy. Después de esa llamada, @strategy es una instancia de Symbol, no .

¿Qué desea hacer? Reemplazar el objeto o actualizarlo?

+0

Oh sry parece que estropeé el método. Debería ser '@strategy << strategy'. – FlyingFoX

+0

Oh; Entonces, ¿una estrategia no tiene una dirección, sino que tienes una lista de estrategias y una dirección actual? – Phrogz

Cuestiones relacionadas