This question is strictly about Struct behavior, so please no "why in the wide world of sports are you doing it that way?"
This code is INCORRECT, but it should illustrate what I am trying to understand about Ruby Structs:
class Person < Struct.new(:name, :last_name)
end
class ReligiousPerson < Person(:religion)
end
class PoliticalPerson < Person(:political_affiliation)
end
### Main ###
person = Person.new('jackie', 'jack')
pious_person = ReligiousPerson.new('billy', 'bill', 'Zoroastrianism')
political_person = PoliticalPerson.new('frankie', 'frank', 'Connecticut for Lieberman')
As you can see, there's an attempt to define a class inheritance using Structs. However, Ruby gets cranky when you try to initialize ReligiousPerson or PoliticalPerson, of course. So given this illustrative code, how is it possible to inherit named params using this type of class inheritance using Structs?
How does Inheritance Work in Ruby? 1 Here class A is the parent class and it contains the method a. 2 Class B and Class C are the subclass which are inheriting the properties of class A. 3 When we use the command B < A and C < A, class C and class B will get the reference of the attributes stored for method A. More items...
How to Create Structs in Ruby. You can create a Struct by calling new & passing in a list of symbols that’ll become the instance variables of this class. They’ll have accessor methods defined by default, both for reading & writing. Here’s an example: Person = Struct.new(:name, :age, :gender) Now you can create a objects like this:
You can also add its own objects, methods in addition to base class methods and objects, etc. Note: By default, every class in Ruby has a parent class. Before Ruby 1.9, Object class was the parent class of all the other classes or you can say it was the root of the class hierarchy.
Fruit (more generic) is the parent class of Orange (more specific). In Ruby it looks like this: One of the implications of inheritance in Ruby is that every method & every constant defined on Food will be available on Fruit, and also on Orange.
You could define new Structs, based in Person:
class Person < Struct.new(:name, :last_name)
end
class ReligiousPerson < Struct.new(*Person.members, :religion)
end
class PoliticalPerson < Struct.new(*Person.members, :political_affiliation)
end
### Main ###
person = Person.new('jackie', 'jack')
p pious_person = ReligiousPerson.new('billy', 'bill', 'Zoroastrianism')
p political_person = PoliticalPerson.new('frankie', 'frank', 'Connecticut for Lieberman')
Result:
#<struct ReligiousPerson name="billy", last_name="bill", religion="Zoroastrianism">
#<struct PoliticalPerson name="frankie", last_name="frank", political_affiliation="Connecticut for Lieberman">
Immediate after posting my answer I had an idea:
class Person < Struct.new(:name, :last_name)
def self.derived_struct( *args )
Struct.new(*self.members, *args)
end
end
class ReligiousPerson < Person.derived_struct(:religion)
end
class PoliticalPerson < Person.derived_struct(:political_affiliation)
end
### Main ###
person = Person.new('jackie', 'jack')
p pious_person = ReligiousPerson.new('billy', 'bill', 'Zoroastrianism')
p political_person = PoliticalPerson.new('frankie', 'frank', 'Connecticut for Lieberman')
Works fine!
You may also add #derived_struct to Struct:
class Struct
def self.derived_struct( *args )
Struct.new(*self.members, *args)
end
end
Ruby gets cranky when you try to initialize ReligiousPerson or PoliticalPerson, of course
I think it's more likely that it's erroring out when you try to define ReligiousPerson
and PoliticalPerson
. This is because Person(:religion)
looks like an attempt to call Person
as if it were a function. Obviously, that's not going to work because Person
is a class.
It's perfectly valid though to subclass Person:
class ReligiousPerson < Person
attr_accessor :religion
def initialize(name, last_name, religion)
super(name, last_name)
@religion = religion
end
end
pious_person = ReligiousPerson.new('billy', 'bill', 'Zoroastrianism')
pious_person.religion #=> "Zoroastrianism"
Struct.new
isn't really doing anything special by the way, it's just dynamically creating a class based on the values you pass it. You are then creating a new class (Person
) which subclasses the class created by Struct.new
:
new_struct = Struct.new(:name, :last_name)
class Person < new_struct
end
Person.superclass == new_struct #=> true
Also, you may want to take note of this property of some of the previous answers:
class Person < Struct.new(:name, :last_name)
end
class ReligiousPerson < Struct.new(*Person.members, :religion)
end
ReligiousPerson.ancestors.include?(Struct) #=> true
ReligiousPerson.ancestors.include?(Person) #=> false
If you do it that way, ReligiousPerson
is actually not a subclass of Person
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With