常见的ref="/tag/2028/" style="color:#2B406D;font-weight:bold;">Ruby基础题
面试官一上来可能不会直接问多复杂的东西,而是先看看你对语言的基本掌握情况。比如,问你 nil 和 false 的区别。在 Ruby 里,只有 false 和 nil 是假值,其他都是真值,连空数组和空哈希都算真。
再比如,==、equal? 和 === 的区别经常被拿来考。简单说,== 比较的是值,equal? 看的是对象是否完全一样(内存地址),而 === 常用于 case 语句中,比如正则匹配:
\/d+\/ === "123" # => true
(1..5) === 3 # => true
块、yield 和 Proc 的使用
写 Ruby 不用块,那基本等于没写。面试时如果问到如何自定义一个支持块的方法,就得用 yield。
def with_log
puts "开始执行"
yield
puts "执行结束"
end
with_log { puts "我在干活" }
# 输出:
# 开始执行
# 我在干活
# 执行结束
如果想把块存起来以后用,就得靠 Proc 或 lambda。两者区别在于参数检查和 return 行为。lambda 对参数更严格,return 只退出自己;而 Proc 的 return 会从外层方法直接跳出。
类与模块的细节问题
Ruby 的模块不能实例化,但能被包含(include)或扩展(extend)。面试常问 include 和 extend 到底有啥不同。
简单说,include 把模块的方法变成实例方法,extend 把它变成类方法。举个例子:
module Greet
def hello
puts "你好"
end
end
class Person
include Greet
end
class Tool
extend Greet
end
Person.new.hello # => 你好
Tool.hello # => 你好
常用方法的手动实现
有时候面试官会让你手写一个 map 方法,看看你对迭代的理解。
def my_map(array)
result = []
for item in array
result << yield(item)
end
result
end
my_map([1, 2, 3]) { |x| x * 2 } # => [2, 4, 6]
或者让你实现一个简单的 memoize 缓存机制,避免重复计算:
def memoize(&block)
cache = {}
lambda { |n|
cache[n] ||= block.call(n)
}
end
fib = memoize do |n|
n <= 1 ? n : fib.(n-1) + fib.(n-2)
end
fib.(10) # 快速返回 55
字符串处理实战题
有个经典题目是判断回文字符串。注意大小写和非字母数字字符的处理。
def palindrome?(str)
cleaned = str.downcase.gsub(/[^a-z0-9]/, '')
cleaned == cleaned.reverse
end
palindrome?("A man, a plan, a canal: Panama") # => true
这种题看着简单,但边界处理容易出错,比如空格、标点、大小写混用的情况。
文件操作相关问题
Ruby 写脚本少不了和文件打交道。面试可能会让你读一个日志文件,统计某类错误出现的次数。
error_count = 0
File.foreach("app.log") do |line|
error_count += 1 if line.include?("ERROR")
end
puts "发现 #{error_count} 个错误"
记得用 foreach 而不是 readlines,避免大文件撑爆内存。
实际项目中的小技巧
在真实工作中,经常需要处理配置文件。YAML 是 Ruby 里的常客。
require 'yaml'
config = YAML.load_file('config.yml')
puts config["database"]["host"]
如果 config.yml 长这样:
database:
host: localhost
port: 5432
这招在写自动化脚本时特别实用,比如部署前自动读取环境配置。