Struct Embedding in Ruby

Our example demonstrates struct embedding in Ruby. While Ruby doesn’t have a direct equivalent to Go’s struct embedding, we can achieve similar functionality using modules and inheritance.

# Define a base class
class Base
  attr_reader :num

  def initialize(num)
    @num = num
  end

  def describe
    "base with num=#{@num}"
  end
end

# Define a container class that includes the Base functionality
class Container < Base
  attr_reader :str

  def initialize(num, str)
    super(num)
    @str = str
  end
end

# Create a new Container instance
co = Container.new(1, "some name")

# We can access the base's fields directly on `co`
puts "co={num: #{co.num}, str: #{co.str}}"

# We can also access the num field through the superclass
puts "also num: #{co.num}"

# Since Container inherits from Base, it has access to Base's methods
puts "describe: #{co.describe}"

# Define a module for the Describer interface
module Describer
  def describe
    raise NotImplementedError, "#{self.class} needs to implement 'describe' method"
  end
end

# We can use the Describer module to check if an object responds to 'describe'
d = co
puts "describer: #{d.describe}" if d.is_a?(Describer)

To run the program:

$ ruby struct_embedding.rb
co={num: 1, str: some name}
also num: 1
describe: base with num=1
describer: base with num=1

In this Ruby example, we use inheritance to mimic struct embedding. The Container class inherits from Base, which allows it to access Base’s methods and attributes.

We also demonstrate the use of modules in Ruby, which can be used to implement interface-like behavior. The Describer module defines a method that should be implemented by classes that include it.

Ruby’s approach to composition and inheritance provides flexibility similar to Go’s struct embedding, allowing for clean and modular code organization.