2016-07-04 40 views
5

Ho un modulo che viene utilizzato principalmente come spazio dei nomi. Chiamiamolo allo Bla. Ci sono altri sottomoduli che hanno metodi con funzioni specifiche per quel sottomodulo.Qual è la differenza tra defdelegate e def con funzione modulo di chiamata direttamente in Elixir

Tuttavia, voglio avere due opzioni:

1) importare modulo principale Bla e utilizzare tutte le funzioni da moduli direttamente (per non scrivere più importazioni separatamente)

2) solo importazione modulo specifico come Bla.Subbla utilizzare le funzioni solo da questo modulo senza funzioni di importazione da altri sottomoduli

questo è quello che ho:

defmodule Bla do 
    defdelegate bla_func(text), to: Bla.Subbla 
    defdelegate bla_func(text, opts), to: Bla.Subbla 
end 

defmodule Bla do 
    def bla_func(text), do: Bla.Subbla.bla_func(text) 
    def bla_func(text, opts), do: Bla.Subbla.bla_func(text, opts) 
end 

Qual è il modo giusto per farlo? Ho due opzioni, ma non ne ho idea, forse, ce n'è una molto più bella. Queste due opzioni sono equivalenti? E quale è preferibile? C'è qualche differenza nelle prestazioni?

+4

Penso che dovresti prendere in considerazione l'uso di 'use' e ​​passare ad esso le opzioni relative a ciò che desideri importare. – JustMichael

+0

suona bene, leggerà di questa opzione (sto solo imparando - non so molto al momento) – kovpack

risposta

4

Poche differenze mi vengono in mente:

  1. Quando si utilizza defdelegate il vostro intento è molto chiaro, si sta solo delegando il metodo per un altro metodo in un altro modulo. E questo è solo uno stupido spedizioniere.
  2. Con defdelegate non è possibile modificare arguments, che si tratti di ordine, aggiunta o rimozione di argomenti. Quindi, se tutto quello che vuoi veramente è di inoltrare la chiamata al metodo usa defdelgate perché c'è meno spazio per rovinare.
  3. In alcuni casi, defdelegate non è un'opzione in quanto è necessario aggiungere più dati alla funzione di inoltro, nel qual caso non si dispone di un'opzione.

Quindi, la linea di fondo è: se possibile utilizzare sempre defdelegate, eviterete alcune classi di bug che lo utilizzano. per esempio. di seguito:

defmodule Greet do 
    def greet(name, greeting) do 
    IO.puts "#{greeting} #{name}" 
    end 
end 

defmodule DelegatedGreet do 
    defdelegate greet(name, greeting), to: Greet 
end 

defmodule BuggyGreet do 
    # scope for bugs like these 
    def greet(name, greeting), do: Greet.greet(greeting, name) 
end 
2

Come ha detto @JustMichael, è opportuno utilizzare use in questo caso. Fa esattamente quello di cui ho bisogno.

defmodule SomeModuleWhereINeedSubbla do 
    use Bla 

    useful_func # => Will print "Bla.Subbla.useful_func" 
end 

defmodule Bla do 
    defmacro __using__(_) do 
    quote do 
     import Bla.Subbla 
    end 
    end 
end 

defmobule Bla.Subbla do 
    def useful_func(), do: IO.puts "Bla.Subbla.useful_func" 
end 
+1

Questa risposta è accettata come alternativa, ma non risponde alla domanda originale. –

+0

yeap, davvero, questa non è una risposta. sarebbe bello sapere se conosci la risposta :) – kovpack

Problemi correlati