【问题标题】:When and when not to use the initialize method in ruby何时以及何时不使用 ruby​​ 中的初始化方法
【发布时间】:2019-12-20 20:04:14
【问题描述】:

我对 ruby​​ 中的初始化方法感到困惑。我正在学习 OOP 并尝试使用 OOP 在 ruby​​ 中制作井字游戏。我想知道什么时候使用initialize方法,什么时候不使用。

只有当我想创建一个新对象时?例如在井字游戏中制作棋盘我必须做 board.new 因为我必须初始化棋盘。

但是,假设我让方法获胜,即使我不需要制作任何对象,该方法是否也需要初始化?

或者是我必须为我制作的每个新课程进行初始化,例如班级委员会或班级玩家或班级胜利

【问题讨论】:

标签: ruby oop


【解决方案1】:

initialize 方法对于需要在对象初始化期间完成某些操作的对象是必需的,仅此而已。有些对象不需要初始化,例如:

class Dog
  def woof
    :arf
  end
end

但是,如果您希望能够自定义这只狗的吠叫方式,您可以给它一个初始化程序:

class Dog
  WOOF_DEFAULT = :arf

  attr_reader :woof

  def initialize(woof)
    @woof = woof || WOOF_DEFAULT
  end
end

现在你可以在初始化时进行配置:

dog = Dog.new(:bork)
dog.woof
# => :bork

您并不总是需要initialize,但当您需要时,它是一个有用的工具。

在板的上下文中,大概你需要创建板:

class Board
  def initialize
    # Create 9 cells, each of which is nil by default
    @cells = Array.new(9, nil)
  end

  def move(x, y, side)
    # Make a move in a cell if the cell is not occupied (||=)
    @cells[x + y * 3] ||= side
  end

  def to_s
    # Produces a string representation of the board state
    @cells.map do |cell|
      cell || ' '
    end.each_slice(3).map do |row|
      row.join(' | ')
    end.join("\n---------\n")
  end
end

现在你有一个可以像这样使用的板:

b = Board.new

puts b
#   |   |  
# ---------
#   |   |  
# ---------
#   |   |  

puts

b.move(0,1, 'X')
b.move(1,0, 'O')

puts b
#   | O |  
# ---------
# X |   |  
# ---------
#   |   |  

【讨论】:

  • 由于只有一块板,您可能会说只有类方法和类实例变量,而没有类的实例。
  • @CarySwoveland 只声明一个类的实例并没有错。拥有一个实例为您提供了模块化和创建多个板的潜力,例如用于测试。
  • 顺便说一句,您的“Takuan Soho 教义的现代化版本”有很多道理。我记得当我学习真正的分析时经历过。只有当早期的概念嵌入我的潜意识时,我才能取得进步。有一天,云散开,似乎是在一瞬间。此后,每当我学到新结果时,我的大脑似乎就会自动运行嵌入过程。这很奇怪,但很棒。我和其他有类似经历的人交谈过。
【解决方案2】:

您可以考虑创建两个类,BoardPlayer。以后者为先,将有两个Player 实例,一个是标记'X' 的玩家,另一个是标记'O' 的玩家。 Player 类有一个 initialize 方法,其功能是保存玩家(实例)将制作的标记('X''O')。

由于只有一个板,我们可以创建 Board 的单个实例,就像 @tadman 所做的那样。另一种选择——我选择的那个——是用三个类方法和一个 class 实例变量 (@cells) 构造类 Board,而不打算创建唯一的实例类的。

我认为Board 类的任何一种方法都不是首选;我只想指出,当一个类表示单个对象时,该对象可以是类本身,而不是类的实例。

你可以如下构造这两个类。

WINNERS = 3.times.with_object([]) do |i,a|
   a << [[i,0], [i,1], [i,2]] << [[0,i], [1,i], [2,i]]
end << [[0,0], [1,1], [2,2]] << [[0,2], [1,1],  c[2,0]]
  #=> [[[0, 0], [0, 1], [0, 2]], [[0, 0], [1, 0], [2, 0]],
  #    [[1, 0], [1, 1], [1, 2]], [[0, 1], [1, 1], [2, 1]],
  #    [[2, 0], [2, 1], [2, 2]], [[0, 2], [1, 2], [2, 2]],
  #    [[0, 0], [1, 1], [2, 2]], [[0, 2], [1, 1], [2, 0]]] 

class Board
  @cells = Array.new(3) { Array.new(3, ' ') }

  def self.record_move(r,c,side)
    @cells[r][c] = side
  end

  def self.win?(side)
    WINNERS.any? { |a| a.all? { |r,c| @cells[r][c] == side } }
  end

  def self.show
    3.times do |i|
      puts "%s|%s|%s" % @cells[i]
      puts "_____" unless i == 2
    end
  end                 
end

请参阅Array::newEnumerable#any?Enumerable#all?

class Player
  def initialize(side)
    @side = side
  end

  def move(r,c)
    Board.record_move(r,c,@side)
  end

  def win?
    Board.win?(@side)
  end
end

x = Player.new('X')
  #=> #<Player:0x000057c0e95c4430 @side="X"> 
o = Player.new('O')
  #=> #<Player:0x000057c0e95e3100 @side="O"> 

Board.show
 | | 
_____
 | | 
_____
 | | 

x.move 0,2
Board.show
 | |X
_____
 | | 
_____
 | |

o.move 0,0
Board.show
O| |X
_____
 | | 
_____
 | | 

x.move 2,0
Board.show
O| |X
_____
 | | 
_____
X| | 
x.win? #=> false 

o.move 2,2
Board.show
O| |X
_____
 | | 
_____
X| |O
o.win? #=> false 

x.move 1,1
Board.show
O| |X
_____
 |X| 
_____
X| |O
x.win? #=> true 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-05
    • 2021-11-10
    • 2015-08-19
    • 1970-01-01
    • 1970-01-01
    • 2011-12-16
    相关资源
    最近更新 更多