In Ruby, when is checking respond_to? before calling a method the right move, and what can respond_to? get wrong?
answer
- optional capabilities, not every call
- private and protected excluded by default
- respond_to?(:puts) is false
- unimplemented methods report false
- method_missing needs respond_to_missing?
basics
~20 sUse respond_to? when a capability is optional and you branch on it, like flushing only if an output supports flush. It ignores private and protected methods unless you pass true, and objects using method_missing report false without respond_to_missing?.
solid answer
~40 s`respond_to?(name, include_all = false)` asks whether a public method exists, so it fits **optional** behaviour: `out.flush if out.respond_to?(:flush)`, or choosing between two code paths by capability. It is the wrong tool for guarding a method you require, because calling it and letting `NoMethodError` surface gives the same failure with less code. Its answers have edges: private and protected methods count only with `include_all = true`, so `Object.new.respond_to?(:puts)` is `false` because `Kernel#puts` is private; methods that exist but are not implemented on the platform, such as `Process.fork` on Windows, report `false`; and an object that handles calls in `method_missing` says `false` unless it also defines `respond_to_missing?`. A true answer also promises nothing about arity or behaviour.
code
ruby · 12 linesdef write_rows(rows, out)
rows.each { |row| out << row.join(",") << "\n" }
out.flush if out.respond_to?(:flush) # optional capability
out
end
write_rows([[1, "a"]], $stdout) # IO: rows written, then flushed
write_rows([[1, "a"]], String.new) # String buffer: no flush, still works
Object.new.respond_to?(:puts) # => false, Kernel#puts is private
Object.new.respond_to?(:puts, true) # => true
$stdout.respond_to?(:flush) # => truego deeper
Recall that respond_to? checks whether an object has a public method, and that private methods such as puts report false by default.
Explain the include_all argument, the unimplemented-method case and why method_missing proxies need respond_to_missing? for honest answers.
Use respond_to? only for optional capabilities or boundary errors, and avoid rescuing NoMethodError in ways that swallow unrelated bugs.
Define how protocols are named and checked across a codebase so capability checks stay rare, meaningful and trustworthy.
## What respond_to? answers `Kernel#respond_to?(name, include_all = false)` returns `true` if calling `name` on the object would find a method. The name may be a Symbol or a String. Its documentation spells out the rules: 1. Only **public** methods count by default; **private and protected** methods are included only when the second argument is truthy. 2. A method that is defined but **not implemented** on this platform, such as `Process.fork` on Windows, reports `false`. 3. If no method is found, Ruby asks **`respond_to_missing?`**, which is how objects built on `method_missing` can answer honestly. ## When a respond_to? check is the right move - **Optional capabilities.** The exporter writes to any output with `<<`, and flushes only outputs that support it: `out.flush if out.respond_to?(:flush)`. A String buffer has no `flush`, an `IO` does, and both work. - **Choosing a strategy.** A method might write rows one at a time from anything with `each`, but take a batched path for an object that responds to `each_slice`, writing a hundred rows per call. - **Friendlier errors at a public boundary.** A library can raise `ArgumentError, "rows must respond to each"` early instead of letting a `NoMethodError` surface three frames deep. In each case the check is about **what the object can do**, which keeps the method open to any class with that capability. ## When it is noise Guarding a method you cannot do without adds code and changes little: ```ruby # noise: fails either way, just with a different message raise ArgumentError unless rows.respond_to?(:each) rows.each { ... } ``` Calling `rows.each` directly raises `NoMethodError` naming the method and the receiver. Keep explicit guards for public APIs where the clearer message is worth it. ## What respond_to? can get wrong | Situation | `respond_to?` says | Reality | |---|---|---| | method is private, like `Kernel#puts` on any object | `false` | callable without a receiver inside the object | | method is protected | `false` | callable from peers of the same class | | method defined but not implemented on the platform | `false` | calling it raises `NotImplementedError` | | proxy answers via `method_missing` only | `false` | the call would work | | method exists but needs two arguments | `true` | calling with one raises `ArgumentError` | Two consequences follow: - **`Object.new.respond_to?(:puts)` is `false`**, a classic interview trap. `puts` is a private `Kernel` method, meant to be called without an explicit receiver; `respond_to?(:puts, true)` returns `true`. - **A `true` answer is only about existence.** It says nothing about arity, keyword arguments or what the method does. Duck typing trusts the name to carry the meaning, so pick distinctive method names for your protocols. ## respond_to? versus rescuing NoMethodError Some code calls first and rescues `NoMethodError` instead. That is riskier than it looks: - The rescue also catches `NoMethodError`s raised **inside** the called method, for example a `nil` deep in the data, and misreports them as "unsupported object". - If you do rescue, verify the error is about this call: `e.receiver.equal?(obj) && e.name == :flush`, and re-raise otherwise. For optional capabilities, the `respond_to?` branch is clearer and cannot swallow unrelated bugs. ## An exporter example Put together, a writer that accepts any output looks like this: it calls `<<` unconditionally, because every supported output (an `IO`, a `StringIO`, a String buffer) must have it, and it calls `flush` only when the output offers it. Required capability: called directly. Optional capability: guarded with `respond_to?`. That split is the whole idiom in one method, and it is the pattern interviewers look for when they ask about `respond_to?`. ## Practical checklist - Use `respond_to?` to **branch on optional** capabilities, not to guard required ones. - Pass `true` as the second argument only when you really mean to include private and protected methods. - When writing a proxy with `method_missing`, also define `respond_to_missing?` so `respond_to?` stays truthful. - Remember that `respond_to?` and `method_missing` together only describe existence; tests are what confirm behaviour.
- Why does `Object.new.respond_to?(:puts)` return false even though `puts` works inside any method?`puts` is a private method of Kernel, meant to be called without an explicit receiver. `respond_to?` considers only public methods unless its second argument is true, so it reports false; `respond_to?(:puts, true)` returns true.
- What must a proxy that forwards calls through `method_missing` also define so that `respond_to?` tells the truth?It must define `respond_to_missing?(name, include_private)` returning true for the names it forwards. `respond_to?` calls it when no real method is found; without it, respond_to? returns false even though calling the method would succeed.
saying these in an interview costs you the question
- respond_to? returns true for private methods by default.
- A true respond_to? answer guarantees the call succeeds with any arguments.
- Every required method call should be guarded with respond_to? first.
- Objects that use method_missing always report true from respond_to?.
- Rescuing NoMethodError around a call only catches the missing method on that object.