在Ruby类中定义类方法和属性的正确方法

时间:2020-08-15 17:07:00

标签: ruby

我试图用Ruby编写一个Person类,该类具有一些方法和属性。下面是我现在如何实现它。

class Person
  attr_accessor :name, :gender, :mother

  def initialize(name, gender, mother)
    @name = name
    @gender = gender
    @mother = mother
    @spouse = nil
  end

  def add_spouse(spouse)
    if spouse
      @spouse = spouse
      spouse.spouse = self
    end
  end
  
  def father(self)
    return [self.mother.spouse]
  end
end

我想访问这样的方法:

m = Person.new('mom', 'Female')
d = Person.new('dad', 'Male')

d.add_spouse(m)

p = Person.new('Jack', 'Male', m)

如果我想获得father中的p,那么我想这样获得它:p.father

那么上述实现是否正确?

如果我运行代码,将会收到以下错误:

person.rb:18: syntax error, unexpected `self', expecting ')'
  def father(self)
person.rb:21: syntax error, unexpected `end', expecting end-of-input

如果我从self中删除了def father(self),则出现此错误:

person.rb:14:in `add_spouse': undefined method `spouse=' for #<Person:0x00005570928382d8> (NoMethodError)

我的错误在这里:attr_accessor :spouse。我必须添加并访问它,我必须做puts(p.father[0].name)

是否有更好的方法来实现具有以上类似属性的上述类,例如fatherchildrenbrothers等?

2 个答案:

答案 0 :(得分:1)

看看-

class Person
  attr_accessor :name, :gender, :mother, :spouse

  def initialize(name, gender, mother)
    @name = name
    @gender = gender
    @mother = mother
    @spouse = nil
  end

  def add_spouse(spouse)
    if spouse
      @spouse = spouse
      @spouse.spouse = self
    end
  end
  
  def father()
    return [self.mother.spouse]
  end
end

输出-

m = Person.new('mom', 'Female', nil)
d = Person.new('dad', 'Male', nil)
d.add_spouse(m)
p = Person.new('Jack', 'Male', m)

正如评论中所写,这是https://codereview.stackexchange.com/

的一个问题。

答案 1 :(得分:1)

在Ruby中,一切都是对象,几乎一切不包括块,等等。 Ruby使用classes作为Objects定义,并建立attributesmethods

您的代码设置了namegendermother的属性,并具有了add_spousefather的方法。因此,父亲被解释既作为属性又作为方法存在明显的混合。从命名约定的角度来看,我们可以重命名该方法collect_father_relation或类似的名称,该方法将处理呈现对象的逻辑。

您也不需要像在return方法中那样显式地编写father,Ruby会为您完成。

我将father方法重新配置为以下内容:

def collect_father_relation
  @mother&.spouse
end

您调用@mother instance_variable,定义实例,并且仅在spouse存在时(可能是@mother)调用nil。 }运算符。

您还应该为&.的母亲准备initialize函数:

nil

这将接受一个母参数,但如果未传递,则不会引发def initialize(name, gender, mother = nil)

最后,您将需要为ArgumentError添加一个attr_accessor,因为您要在{{1}中设置关系时要明确引用配偶Person对象的:spouse }

其他评论:

让我们为spouse方法创建一个保护子句(如上所述),以明确说明我们在做什么,而不是模棱两可的if语句。

spouse.spouse = self
相关问题