Ruby variables d'instance privée, avec des exceptions
-
24-09-2019 - |
Question
Je fais un jeu de cartes en ruby.
J'ai la classe de jeu, qui a un tableau d'objets joueur.
array_of_players = Array[
Player.new("Ben"),
Player.new("Adam"),
Player.new("Peter"),
Player.new("Fred"),
]
my_game = Game.new(array_of_players)
puts my_game.players[2].name #=> Peter
Chaque joueur a également accès au jeu, afin qu'ils puissent accéder aux morceaux importants du jeu comme si
self.game.last_card_dealt
Chaque joueur a également des cartes (Player.cards), et je veux faire en sorte que les joueurs ne peuvent pas accéder aux cartes de l'autre. Cependant, le jeu a besoin d'un accès aux cartes, donc je ne pense pas que l'utilisation private
est appropriée, et les joueurs ont besoin d'accéder à certaines informations de l'autre, donc je ne pense pas que je veux que ce soit private
soit ...
En fait, je veux que ces travailler.
self.cards #where self is a Player object
self.players[0].cards #where self is the Game
self.game.players[0].name #where self is a Player object
Et cela à l'échec:
self.hand.players[0].cards #=> Nice try sucker! Cheating is for losers.
Comment sont des permissions plus complexes comme celui-ci traitées? Merci.
La solution 4
Merci pour toutes vos réponses.
En fin de compte je me suis dit que je pouvais donner l'objet autorisé une clé qui est utilisée pour lui permettre l'accès à la viande d'une méthode.
objet de jeu a @auth_object et il met à l'objet joueur a l'intention d'accéder aux méthodes secrètes de, et les contrôles de méthode secrète du joueur si hand.auth_object est self
, sinon il ne fait rien. Ensuite @auth_object est remis à zéro. Il y a un attr_reader mais aucun écrivain pour @auth_object.
Cela fonctionne.
Autres conseils
Ceci est plus pratique que mon autre réponse, et utilise l'objet du jeu en tant que délégué à toutes les informations dans le jeu lui-même (joueurs, cartes, etc.). Notez que vous devez toujours faire confiance à l'appelant de se faire passer, mais sérieusement où tirez-vous la ligne?
class Player
attr_reader :name
def initialize(name)
@name = name
end
end
class Cards
attr_accessor :cards
end
class Game
attr_reader :name, :players
def initialize(players)
@name = "Game Master"
@hands = []
@players = players.each do |p|
puts "Added %s to game." % p.name
@hands << {:player => p, :cards => Cards.new}
end
end
def view_hand(player, caller)
@hands.each do |hand|
if hand[:player] == player
if hand[:player] == caller or caller == self
puts "%s: You can access all these cards: %s" % [caller.name, hand[:cards]]
else
# Do something to only display limited cards depending on this caller's view capabilities
puts "%s: You can only access the cards I will let you see: %s" % [caller.name, hand[:cards]]
end
end
end
end
def my_cards(player)
@hands.each do |hand|
puts "%s's cards: %s" % [player.name, hand[:cards]] if hand[:player] == player
end
end
end
g = Game.new([Player.new('Bob'), Player.new('Ben')])
puts "\nCalling each Player's cards as each Player:\n\n"
g.players.each do |gp|
g.players.each do |p|
g.view_hand(gp, p)
end
end
puts "\nCalling each Player's cards as Game:\n\n"
g.players.each do |p|
g.view_hand(p, g)
end
puts "\nEach Player calls for their own cards:\n\n"
g.players.each do |p|
g.my_cards(p)
end
La sortie:
Added Bob to game.
Added Ben to game.
Calling each Player's cards as each Player:
Bob: You can access all these cards: #<Cards:0x100121c58>
Ben: You can only access the cards I will let you see: #<Cards:0x100121c58>
Bob: You can only access the cards I will let you see: #<Cards:0x100121bb8>
Ben: You can access all these cards: #<Cards:0x100121bb8>
Calling each Player's cards as Game:
Game Master: You can access all these cards: #<Cards:0x100121c58>
Game Master: You can access all these cards: #<Cards:0x100121bb8>
Each Player calls for their own cards:
Bob's cards: #<Cards:0x100121c58>
Ben's cards: #<Cards:0x100121bb8>
Gardez privée Game.player
pour interdire les joueurs d'accéder à d'autres joueurs à travers le réseau.
par exemple. Quand un joueur est self
, self.game.players[0].name
est un peu ridicule.
Peut-être que vous voulez une méthode de Game.player_names
public qui retourne juste un tableau de noms de joueurs?
En plus de cela, vous pourriez faire une méthode de Players.opponents
public.
Exemples
Game.player_names
class Game
# ...
def player_names
self.players.collect { |p| p.name }
end
private
# private game methods
end
Player.opponents
class Player
# ...
def opponents(i=nil)
return i.nil? ? self.game.player_names : self.game.player_names[i]
end
end
Ce fut amusant de jouer avec. Je ne suis pas sûr que ce soit la meilleure réponse possible, mais il fonctionne. La clé est de passer l'objet appelant à Player.cards (obj) et vérifier si elle est soit le joueur lui-même, ou de type de jeu, qui ont tous deux accès légal.
class Player
attr_accessor :name, :game
attr_writer :cards
def initialize(name)
@name = name
@game = nil
@cards = nil
end
def cards(caller)
puts "%s cards called by %s." % [self, caller]
if caller.kind_of?(Game) or caller == self
puts "Here's your cards %s." % @cards
else
puts "Nice try sucker! Cheating is for losers."
end
end
end
class Cards
def initialize
@cards = [1, 2, 3]
end
end
class Game
attr_reader :players
def initialize(players)
@players = players.each do |p|
puts "Added %s to game." % p.name
p.game = self
p.cards = Cards.new
end
end
end
g = Game.new([Player.new('Bob'), Player.new('Ben')])
puts "\nCalling each Player's cards as each Player:\n\n"
g.players.each do |gp|
g.players.each do |p|
p.cards(gp)
end
end
puts "\nCalling each Player's cards as Game:\n\n"
g.players.each do |p|
p.cards(g)
end
Et la sortie:
Added Bob to game.
Added Ben to game.
Calling each Player's cards as each Player:
#<Player:0x100122b30> cards called by #<Player:0x100122b30>.
Here's your cards #<Cards:0x1001229c8>.
#<Player:0x100122ae0> cards called by #<Player:0x100122b30>.
Nice try sucker! Cheating is for losers.
#<Player:0x100122b30> cards called by #<Player:0x100122ae0>.
Nice try sucker! Cheating is for losers.
#<Player:0x100122ae0> cards called by #<Player:0x100122ae0>.
Here's your cards #<Cards:0x100122928>.
Calling each Player's cards as Game:
#<Player:0x100122b30> cards called by #<Game:0x100122ab8>.
Here's your cards #<Cards:0x1001229c8>.
#<Player:0x100122ae0> cards called by #<Game:0x100122ab8>.
Here's your cards #<Cards:0x100122928>.