这个问题严格关于结构行为,所以请不要“为什么在广泛的体育世界中你这样做呢?”
这段代码是不正确的,但它应该说明我想要了解的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')
如您所见,尝试使用Structs定义类继承。但是,当你尝试初始化ReligiousPerson或PoliticalPerson时,Ruby会变得暴躁。所以给定这个说明性代码,如何使用Structs使用这种类继承来继承命名参数?
答案 0 :(得分:16)
您可以定义新的Structs,基于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')
结果:
#<struct ReligiousPerson name="billy", last_name="bill", religion="Zoroastrianism">
#<struct PoliticalPerson name="frankie", last_name="frank", political_affiliation="Connecticut for Lieberman">
在发布我的回答后,我立即知道了:
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')
工作正常!
您也可以将#derived_struct添加到Struct:
class Struct
def self.derived_struct( *args )
Struct.new(*self.members, *args)
end
end
答案 1 :(得分:2)
当你尝试初始化ReligiousPerson或PoliticalPerson时,Ruby会变得暴躁,当然
我认为当你尝试定义 ReligiousPerson
和PoliticalPerson
时,它更有可能出错。这是因为Person(:religion)
看起来像是试图调用Person
,就像它是一个函数一样。显然,这不会起作用,因为Person
是一个类。
尽管继承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
并没有真正做任何特别的事情,它只是根据你传递的值动态创建一个类。然后,您正在创建一个新类(Person
),该类是由Struct.new
创建的类的子类:
new_struct = Struct.new(:name, :last_name)
class Person < new_struct
end
Person.superclass == new_struct #=> true
另外,您可能需要注意以前的一些答案的这个属性:
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
如果您这样做,ReligiousPerson
实际上不是 Person
的子类。
答案 2 :(得分:0)
不,结构不应该在继承链中使用(将 struct 继承形成另一个结构没有多大意义,真的)。您可能要做的是创建自己的 Struct 类并实现相同的行为,但将属性名称存储在继承的类变量中(使用class_inheritable_accessor)。
但我真的不明白为什么会有这样的事情需要。