2011-01-29 3 views
1

저는 프로그래밍에 익숙하지 않지만 배우기를 열심히하니이 질문을 용서하십시오. 나는 OOP를 배우는 것을 돕기 위해이 게임을 만들었고 나는 그것의 일부로 문제를 겪고있다. 다음은 문제의 원인입니다.Ruby> 다른 클래스의 메서드 내에서 한 클래스의 메서드를 사용하려면 어떻게해야합니까?

두 클래스가 있습니다. Player 클래스의 3 번 줄에는 약간 잘못된 코드가 있지만 기본적으로 플레이어가받는 피해를 수정하기 위해 갑옷을 사용하고 있습니다. "NilClass (NoMethodError)에 대한 정의되지 않은 메소드 '보호'

다른 클래스의 Armor가 있습니다.이 문제는 @ armor.protection을 호출한다는 사실과 관련이 있다고 생각합니다. Armor와 Armor에 보호 기능이 언급되어있을 때 Player에서 언급되었지만이를 해결하는 방법이 확실하지 않습니다. 아래 질문과 관련이 있다고 생각되는 코드를 모두 추가했습니다. 그렇게 멍청한 놈이 이해할 수있는 용어를 사용하십시오

class Player 
    def equip(armor) 
    @armor = armor 
    end 

    def hit(damage) 
    #damage = damage - @armor.protection 
    @health -= damage 
    end 
end 

class Armor 
    def initialize(name, protection) 
    @protection = protection 
    end 
end 

편집 :.. 내가 해명을 진행 뭘 찾았는지 모두 표시하기 위해 추가 코드를 추가 을 나는 사람이 내가했습니다 무엇을 모두 읽을 기대하지 않습니다 있어, 그래도. : S 그것은 아마도 두렵고 무서운 것입니다. : P

class Player 

    def initialize(name, health) 
    @name = name 
    @health = health 
    end 

    def equip(armor) 
    @armor = armor 
    end 

    def health 
    @health 
    end 

    def health=(value) 
    @health = value 
    end 

    def hit(damage) 
damage = damage - @armor.protection 
    @health -= damage 
    end 

    def dead? 
if @health <= 0 
return true 
elsif @health > 0 
return false 
end 
    end 

    def name 
    @name 
    end 

    def attack(target) 
    damage = rand(30) 
    puts "#{@name} attacks #{target.name}" 
target.hit(damage) 
puts "#{@name} hits #{target.name} for #{damage} damage." 
    end 
end 

class Armor 
    def initialize(name, protection) 
    @protection = protection 
    end 
end 


player1 = Player.new("Melanie", 100) 
player2 = Player.new("a Monster", 200) 
shirt = Armor.new('shirt', 4) 
player1.equip(shirt) 

while player1.dead? == false && player2.dead? == false 
    player1.attack(player2) 
    if player2.health > 0 
     puts "#{player2.name}'s health is at #{player2.health}." 
    elsif player2.health <= 0 
puts "#{player2.name} has no health." 
end 
    player2.attack(player1) 
    if player1.health > 0 
     puts "#{player1.name}'s health is at #{player1.health}." 
    elsif player1.health <= 0 
puts "#{player1.name} has no health." 
end 
end 

if player1.health > player2.health 
    puts "#{player2.name} is dead." 
    puts "#{player1.name} wins." 
elsif player2.health > player1.health 
    puts "#{player1.name} is dead." 
    puts "#{player2.name} wins." 
elsif player2.health == player1.health 
    puts "#{player1.name} and #{player2.name} killed each other." 
end 

답변

3

, 그것을 잘 작동합니다. 그러나, 그렇지 않기 때문에, 당신이 Armor 클래스 내부에서 호출한다고하더라도, 당신은 같은 에러를 보게 될 것입니다. 정의하려면 attr_reader 또는 attr_accessor을 사용하거나 직접 정의하십시오.

class Armor 
    attr_accessor :protection 

    def initialize(name, protection) 
    @protection = protection 
    end 
end 

또는

class Armor 
    def initialize(name, protection) 
    @protection = protection 
    end 

    def protection 
    @protection 
    end 
end 
+0

현재,이 프로그램은 갑옷을 말하면,이 플레이어의 경우 셔츠라는 것을 알지 못합니다. 내가 armor, 소문자 a, damage = damage 외에도[email protected] armor.protection은 Player 클래스에 장비에 대한 정의가있는 유일한 언급입니다. 두 번째 예제를 처리하려고했지만 두 경우 모두 여전히 동일한 오류가 발생했습니다. 나는 내 머리를 조금 넘는 것을 알고 있지만, 나는 그것을 많이 이해하고 있으며 그것은 분명히 학습 경험이다. : S –

+0

@Melanie : 우선 보호 장치에 대해 언급했을 때 실수로 갑옷을 입력했기 때문에 코드가 잘못되었습니다. 작동하지 않습니다. 이제는 그것을 고쳤으며'@ armor'를 사용하는 메소드를 호출하기 전에'equip'을 호출하면 작동 할 것입니다. – sepp2k

+0

'equip' 호출을 요구하는 더 좋은 해결책은'Player' 클래스'initialize' 메소드에서'Armor' 클래스를 'Armor' 클래스 인스턴스로 초기화하는 것입니다. 그렇게하면 플레이어가 갑옷없이 시작하면 걱정할 필요가 없습니다. –

1

이 시도 : 방어구 클래스는 protection 방법이있는 경우

player = Player.new 
armor = Armor.new('Mythril', 100) 
player = player.equip(armor) #Initialise the armor object inside Player. 

player.hit(10) 
+1

은 player = Player.new 및 player.equip (armbor) 및 player.hit (10)이어야하며 이는 모두 인스턴스 메서드입니다. – Joelio

+0

나는 이미 그런 종류의 것을 가지고 있다고 생각한다. 내가 분명히해야 할 모든 코드를 추가했습니다. 바라건대 그것은 의미가 있습니다. –

1

문제는 여기에 당신이 @protection 인스턴스 변수를 가지고있다,하지만 "접근"은 그것을 얻을 수 있습니다. 인스턴스 변수는 소유하고있는 클래스의 인스턴스에 대해 private이므로 외부 세계에 노출 시키려면 접근자를 설정해야합니다. 이 경우, 당신이 원하는 :

class Armor 
    attr_reader :protection 
    ... 
end 

이것은 당신이 @armor.protection를 호출 방어구 인스턴스의 @protection 변수의 값을 반환하게됩니다.

+0

이것은 확실히 전에 attr_reader, attr_accessor를 이해하는 데 도움이되었습니다. 왜냐하면 전에는 "얻지 못했기"때문에 문제가되었지만, 저는이 문제의 일부가 갑옷에 갑옷을 묶지 않았다고 생각합니다. 어떻게해야할지 모르겠습니다. 지금 당장이 프로그램은 갑옷을 말하면,이 플레이어의 경우 셔츠라는 것을 알지 못합니다. 내가 armor, 소문자 a, damage = damage 외에도[email protected] armor.protection은 Player 클래스에 장비에 대한 정의가있는 유일한 언급입니다. : S –

2

방금 ​​두 번째 (전체) 예제를 실행했습니다. 접근 문제 외에도

는 다른 답변에서 설명 (단지 클래스 Armorattr_reader :protection 추가), 당신은 테스트 시나리오에 뭔가를 :) 간과

오류 메시지가 힌트를 제공합니다 undefined method 'protection' for nil:NilClass (NoMethodError). 이것은 hit 메서드의 첫 번째 줄에서 발생했기 때문에 @armornil이고 물론 nilArmor이 아니므로 protection 메서드가 없습니다. 왜 그게 없습니까?

player1 = Player.new("Melanie", 100) 
player2 = Player.new("a Monster", 200) 
shirt = Armor.new('shirt', 4) 
player1.equip(shirt) 

만 멜라니는 셔츠를 가지고, 당신은 모든 몬스터에게 갑옷을 포기하지 : 음, 당신의 싸움이 시작 방법에 대해 알아!그다지 공평하지는 않습니다 :

수정하려면 갑옷을 달거나 hit 메서드를 변경하여 @armor이 초기화되지 않은 경우에도 작동하도록합니다. 그 일의 좋은 OO 방법은 어떤 보호를 제공하지 않는 기본 더미 갑옷과 모든 선수를 초기화하는 것입니다

class Player 
    def initialize(name, health) 
    @armor = Armor.new('nothing', 0) 
    # ... 

가 완료! 그 더미 갑옷이 게임의 특정 규칙이 어떤 도움이 될 것입니다 때문에


이제, 내가 대신 그것을 만들기위한 책임 클래스 Armor함으로써 클래스 Player의 관점에서 추상을 거라고 :

class Armor 
    class << self # define a class method, like new 
    def none 
     self.new('nothing', 0) 
    end 
    end 
    # ... 

그럼 그냥 Player.initialize에서 Armor.none 대신 Armor.new('nothing', 0)을 말할 수 있습니다. 이렇게하면 Armor의 작동 방식을 변경해야 할 경우 더미 갑옷을 다른 클래스를 건드리지 않고 동시에 업데이트 할 수 있습니다.

+0

와우! 그 놀라운! 정말 고맙습니다! 그게 백만 년 동안의 문제라고 생각하지 않았을 것입니다. 나는 오류 메시지를 더 잘 읽는 법을 배워야 할 것이다. 적어도 나는 "OMG!"오류에서부터 몇 단계 나아갔습니다. –

+0

당신을 진심으로 환영합니다. BTW, 좀 더 질질 끌 수 있다면, 나는 player1.dead를 보았습니다. == 거짓 && player2.dead? == false' ... 서투른 스타일! 최소한'some_boolean == false'를'not some_boolean'으로 대체하십시오; 개인적으로 나는'죽었던'술어를'살아있는'것으로 바꿀 것입니다 : 당신이 부정없이 직접 사용할 수있는 것 : –

+0

그래, 그게 내 친구가 말한거야! 고맙습니다! –

관련 문제