用方法链理解自我

时间:2015-05-14 14:28:05

标签: ruby methods self

我正试图在Ruby中理解自我。

在下面粘贴的代码中,如果我使用

创建一个新的Animal实例

fox = Animal.new.name("Fox").color("red").natural_habitat("forest").specie("mammal")

然后致电

fox.to_s

如果我不在每种方法中返回自我,它什么都不做。

为什么我在每种方法中都需要自我?创建新动物后,该变量是否已保存?

class Animal
  def name(name)
    @name = name
    self
  end
  def specie(specie)
    @specie = specie
    self 
  end
  def color(color)
    @color = color
    self 
  end
  def natural_habitat(natural_habitat)
    @natural_habitat = natural_habitat
    self 
  end
  def to_s
    "Name: #{@name}, Specie: #{@specie}, Color: #{@color}, Natural Habitat: #{@natural_habitat}"
  end
    end

3 个答案:

答案 0 :(得分:3)

这种模式在Ruby中很少使用,它在Java和JavaScript等语言中更为常见,它在jQuery中显得十分猖獗。部分原因在于您在此处描述的详细程度,其次是因为Ruby以attr_accessorattr_writer的形式提供了方便的mutator生成器。

这些存取器/增变器双重用途方法的一个问题是模糊性。您的实施不完整,您无法从中读取。你需要的是:

def color(*color)
  case (color.length)
  when 1
    @color = color
    self
  when 0
    @color
  else
    raise ArgumentError, "wrong number of arguments (%d for 0)" % color.length
  end
end

实现可以通过两种方式使用的东西的大量代码:

animal.color('red')
animal_color = animal.color

如果你想使用它们,你需要编写自己的元编程方法来生成它们,尽管我一开始就非常不鼓励沿着这条路走下去。使用attr_accessor方法和选项Hash。

这里是等效的Ruby模式:

# Up-front assignment via Hash
animal = Animal.new(
  name: 'Fox',
  color: 'red',
  natural_habitat: 'forest',
  specie: 'mammal'
)

# Assignment after the fact
animal.color = 'white'

答案 1 :(得分:1)

在您的示例中,使用self作为返回值很方便。方法返回实例本身,以便您可以调用:

fox = Animal.new
fox.name("Fox").color("red").natural_habitat("forest").specie("mammal")

fox.name("Fox")的值是实例本身,这就是您可以在其上调用.color("red")的原因。

答案 2 :(得分:1)

如果#name方法在没有调用self的情况下实现,就像这样:

Animal.new.name.specie

此方法在调用时将返回一个字符串。

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    let collectionViewWidth: CGFloat  = collectionView.frame.size.width 
    let cellSize: CGFloat = collectionViewWidth / 2.0
    return CGSizeMake(cellSize, cellSize);
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
    return UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
   return 0.0
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
    return 0.0
}

这意味着

{{1}}

会在字符串对象上调用#specie方法(可能会引发NotImplemented错误),而不是实现该方法的Animal类的对象。