Risposte:
Il sovraccarico del metodo può essere ottenuto dichiarando due metodi con lo stesso nome e firme diverse. Queste diverse firme possono essere:
method(int a, int b) vs method(String a, String b)
method(a) vs method(a, b)
Non è possibile ottenere il sovraccarico del metodo utilizzando il primo modo perché non esiste una dichiarazione del tipo di dati in ruby ( linguaggio tipizzato dinamico ). Quindi l'unico modo per definire il metodo sopra èdef(a,b)
Con la seconda opzione, potrebbe sembrare che possiamo ottenere un sovraccarico del metodo, ma non possiamo. Supponiamo che io abbia due metodi con un numero diverso di argomenti,
def method(a); end;
def method(a, b = true); end; # second argument has a default value
method(10)
# Now the method call can match the first one as well as the second one,
# so here is the problem.
Quindi ruby deve mantenere un metodo nella catena di ricerca del metodo con un nome univoco.
"Sovraccarico" è un termine che semplicemente non ha nemmeno senso in Ruby. Fondamentalmente è un sinonimo di "spedizione argomento-base statica", ma Ruby non avere la spedizione statica a tutti . Quindi, il motivo per cui Ruby non supporta l'invio statico in base agli argomenti, è perché non supporta l'invio statico, punto. Non supporta l'invio statico di alcun tipo , basato su argomenti o altro.
Ora, se in realtà non stai chiedendo in modo specifico di sovraccaricare, ma forse di un invio dinamico basato su argomenti, la risposta è: perché Matz non l'ha implementato. Perché nessun altro si è preso la briga di proporlo. Perché nessun altro si è preso la briga di implementarlo.
In generale, l'invio dinamico basato su argomenti in una lingua con argomenti opzionali e liste di argomenti a lunghezza variabile, è molto difficile da ottenere, e ancora più difficile da mantenere comprensibile. Anche nei linguaggi con invio statico basato su argomenti e senza argomenti opzionali (come Java, per esempio), a volte è quasi impossibile dire per un semplice mortale quale sovraccarico verrà scelto.
In C #, puoi effettivamente codificare qualsiasi problema 3-SAT in risoluzione di sovraccarico, il che significa che la risoluzione di sovraccarico in C # è NP-difficile.
Ora provalo con l' invio dinamico , dove hai la dimensione temporale aggiuntiva da tenere in testa.
Ci sono lingue che inviano dinamicamente in base a tutti gli argomenti di una procedura, al contrario dei linguaggi orientati agli oggetti, che inviano solo self
sull'argomento zeroth "nascosto" . Il Lisp comune, ad esempio, invia i tipi dinamici e persino i valori dinamici di tutti gli argomenti. Clojure invia una funzione arbitraria di tutti gli argomenti (che BTW è estremamente interessante ed estremamente potente).
Ma non conosco nessun linguaggio OO con invio dinamico basato su argomenti. Martin Odersky ha affermato che potrebbe prendere in considerazione l'aggiunta di spedizioni basate su argomenti a Scala, ma solo se è in grado di rimuovere contemporaneamente il sovraccarico ed essere retrocompatibile sia con il codice Scala esistente che utilizza il sovraccarico sia compatibile con Java (ha menzionato in particolare Swing e AWT che svolgono alcuni trucchi estremamente complessi esercitando praticamente ogni brutto caso di dark corner delle piuttosto complesse regole di sovraccarico di Java). Ho avuto alcune idee su come aggiungere un invio basato su argomenti a Ruby, ma non sono mai riuscito a capire come farlo in un modo retrocompatibile.
def method(a, b = true)
non funzionerà, quindi il sovraccarico del metodo è impossibile". Non è; è solo difficile. Ho trovato QUESTA risposta davvero istruttiva, comunque.
Presumo che tu stia cercando la possibilità di farlo:
def my_method(arg1)
..
end
def my_method(arg1, arg2)
..
end
Ruby lo supporta in un modo diverso:
def my_method(*args)
if args.length == 1
#method 1
else
#method 2
end
end
Un modello comune è anche quello di passare le opzioni come hash:
def my_method(options)
if options[:arg1] and options[:arg2]
#method 2
elsif options[:arg1]
#method 1
end
end
my_method arg1: 'hello', arg2: 'world'
spero che aiuti
Il sovraccarico del metodo ha senso in un linguaggio con tipizzazione statica, in cui è possibile distinguere tra diversi tipi di argomenti
f(1)
f('foo')
f(true)
nonché tra diversi numeri di argomenti
f(1)
f(1, 'foo')
f(1, 'foo', true)
La prima distinzione non esiste nel rubino. Ruby utilizza la digitazione dinamica o "digitazione anatra". La seconda distinzione può essere gestita da argomenti predefiniti o lavorando con argomenti:
def f(n, s = 'foo', flux_compensator = true)
...
end
def f(*args)
case args.size
when
...
when 2
...
when 3
...
end
end
Questo non risponde alla domanda sul perché ruby non abbia un metodo di overload, ma le librerie di terze parti possono fornirlo.
La libreria contract.ruby consente il sovraccarico. Esempio adattato dal tutorial:
class Factorial
include Contracts
Contract 1 => 1
def fact(x)
x
end
Contract Num => Num
def fact(x)
x * fact(x - 1)
end
end
# try it out
Factorial.new.fact(5) # => 120
Si noti che questo è in realtà più potente del sovraccarico di Java, perché è possibile specificare valori da abbinare (ad es. 1
), Non semplicemente tipi.
Vedrai prestazioni ridotte usando questo però; dovrai eseguire benchmark per decidere quanto puoi tollerare.
Faccio spesso la seguente struttura:
def method(param)
case param
when String
method_for_String(param)
when Type1
method_for_Type1(param)
...
else
#default implementation
end
end
Ciò consente all'utente dell'oggetto di utilizzare il nome_metodo pulito e chiaro: metodo Ma se vuole ottimizzare l'esecuzione, può chiamare direttamente il metodo corretto.
Inoltre, rende i test più chiari e migliori.
ci sono già ottime risposte sul perché lato della domanda. tuttavia, se qualcuno è alla ricerca di altre soluzioni , controlla la gemma funzionale-rubino che si ispira alle caratteristiche di corrispondenza del motivo elisir .
class Foo
include Functional::PatternMatching
## Constructor Over loading
defn(:initialize) { @name = 'baz' }
defn(:initialize, _) {|name| @name = name.to_s }
## Method Overloading
defn(:greet, :male) {
puts "Hello, sir!"
}
defn(:greet, :female) {
puts "Hello, ma'am!"
}
end
foo = Foo.new or Foo.new('Bar')
foo.greet(:male) => "Hello, sir!"
foo.greet(:female) => "Hello, ma'am!"