Ruby类构造函数优化:如何用Hash优化Bank类实现?
Great question! Let's break this down step by step—first fixing the constructor with hash-based parameters, then exploring other ways to polish the class.
Using Keyword Arguments (Modern Ruby's Go-To Approach)
The original constructor's biggest flaw is its reliance on positional parameters: you have to memorize the exact order of arguments, and instantiating the class becomes a messy list of values where it's hard to tell what each one means. Keyword arguments (which are essentially a hash under the hood) solve this by making calls explicit and order-agnostic.
Here's the cleaned-up constructor, fixing the original typos and undefined variables along the way:
class Bank # Required keyword arguments marked with :, optional ones can have defaults def initialize( name:, city:, country:, coordinates:, max_credit_value:, min_credit_value:, credit_time:, interest_rate: 0.05 # Default to 5% if not provided ) @name = name @city = city @country = country @coordinates = coordinates @max_credit_value = max_credit_value @min_credit_value = min_credit_value @credit_time = credit_time @interest_rate = interest_rate end end
Now creating a Bank instance is way more readable and less error-prone:
my_bank = Bank.new( name: "Global Trust Bank", city: "New York", country: "USA", coordinates: { lat: 40.7128, lng: -74.0060 }, max_credit_value: 100000, min_credit_value: 5000, credit_time: 60, # Months interest_rate: 0.075 )
Legacy Alternative: Options Hash
If you're working with older Ruby versions (pre-2.0) that don't support keyword arguments, you can use a single options hash parameter:
class Bank def initialize(options) @name = options[:name] @city = options[:city] @country = options[:country] @coordinates = options[:coordinates] @max_credit_value = options[:max_credit_value] @min_credit_value = options[:min_credit_value] @credit_time = options[:credit_time] @interest_rate = options[:interest_rate] || 0.05 # Fallback default end end
Note: Keyword arguments are better here because they enforce required parameters (you'll get an error if you omit a mandatory one), whereas the options hash would silently set missing values to nil unless you add extra validation.
Other Optimization Opportunities for the Bank Class
Now that the constructor is sorted, here are other ways to improve the class:
Add Input Validation: Prevent invalid state by checking parameters upfront:
def initialize(...) super raise ArgumentError, "Max credit must exceed min credit" if @max_credit_value <= @min_credit_value raise ArgumentError, "Credit time must be positive" if @credit_time <= 0 raise ArgumentError, "Interest rate must be between 0 and 1" if @interest_rate < 0 || @interest_rate > 1 endUse Attribute Accessors: Avoid writing manual getter/setter methods by using
attr_reader(for read-only access) orattr_accessor(for read-write):class Bank attr_reader :name, :country, :interest_rate attr_accessor :credit_time # Allow updating credit time if needed # ... initialize method endEncapsulate Computed Values: If
interest_ratedepends on other factors (like country or credit duration), move that logic into a private method instead of passing it as a parameter:class Bank def initialize(name:, city:, country:, credit_time:, ...) # ... other assignments @interest_rate = calculate_interest_rate(country, credit_time) end private def calculate_interest_rate(country, credit_time) base_rate = country == "USA" ? 0.05 : 0.06 base_rate + (credit_time / 12) * 0.01 # Add 1% per year of credit term end endFix Original Bugs: The original code referenced undefined variables (
coordBainatesandinterest_rate)—ensure all instance variables are properly assigned from parameters or computed values.Add Documentation: Use comments to clarify ambiguous parameters (e.g., is
credit_timein months or years?) and the class's purpose.
内容的提问来源于stack exchange,提问作者Morozov

