Не удалось получить доступ к защищенному методу в Ruby

Я изучал концепцию инкапсуляции в ruby.

Ниже приведен пример кода, ноутбук наследуется от машины, я сделал защищенный метод (класс машины), но не могу получить доступ через экземпляр ноутбука.

Кроме того, я не могу получить доступ к защищенному методу ноутбука, называемому описанием.

class Machine

  attr_accessor :name,:cost  generated

  protected
  def eat
    puts "machine don't eat"
  end

end


class Laptop < Machine

  private
  def ram
    return "4gb"
  end

  private
  def core
    return "i3"
  end

  protected
  def description
    puts "The laptop has #{ram} ram and it has #{core} core"
  end
end

laptop=Laptop.new
laptop.name = "hp_notebook_15_n205tx"
laptop.cost =44000

puts "laptop is a machine, & #{laptop.eat} "  #doesn't work
puts "#{laptop.name} costs #{laptop.cost}"
puts "#{laptop.description}"                  #doesn't work

Ниже приведена ошибка, которую я получил:

`<top (required)>': protected method `eat' called for #<Laptop:0x2ed3b68 @name = "hp_notebook_15_n205tx", @cost=44000> (NoMethodError)
    from -e:1:in `load'
    from -e:1:in `<main>'
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
0
0
116
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Защищенные методы могут вызываться только методами, инкапсулированными в самом классе или подклассе, а не напрямую из экземпляра класса/подкласса. Если вы хотите, чтобы метод eat вызывался из экземпляра, сделайте его общедоступным или вызовите его из другого общедоступного метода:

[19] pry(main)> class Machine
[19] pry(main)*   protected
[19] pry(main)*   def eat
[19] pry(main)*     puts "eating"
[19] pry(main)*   end
[19] pry(main)* end
:eat
[20] pry(main)> class Laptop < Machine
[20] pry(main)*   def chow
[20] pry(main)*     self.eat
[20] pry(main)*   end
[20] pry(main)* end
:chow
[21] pry(main)> l = Laptop.new
#<Laptop:0x007f9c92b5c968>
[22] pry(main)> l.chow
eating
nil

Метод, помеченный как защищенный, означает, что его могут использовать только экземпляры класса, в котором он был определен, или производные классы. Источник: Изучение Ruby Майкла Фицджеральда.

AConsumer 17.02.2019 16:23

Также см.: en.wikibooks.org/wiki/Ruby_Programming/Синтаксис/Классы

AConsumer 17.02.2019 16:25

утверждение, что экземпляры класса могут использоваться, вводит в заблуждение и в значительной степени не соответствует действительности. Он может использоваться классом и подклассами ВНУТРЕННИ. Разница между private и protected заключается в том, что частные методы не могут использоваться подклассами.

ptierno 17.02.2019 16:28

да. Но вы не используете его в экземпляре класса, в котором он был определен, или в производном классе. Вы используете его на верхнем уровне, то есть в Object.

Jörg W Mittag 17.02.2019 16:28

@JörgWMittag, см. Метод описания класса Laptop, также в ruby ​​создание экземпляра не означает создание объекта?

AConsumer 17.02.2019 16:33

да. description защищен. Это означает, что вы можете вызывать его в Laptop и во всех его подклассах. Но вы называете это Object, который не является подклассом Laptop.

Jörg W Mittag 17.02.2019 16:35

Вы называете это on экземпляром Laptop, а не in экземпляром Laptop .. это лучше объясняет?

ptierno 17.02.2019 16:36

Вы не можете получить доступ к защищенным или частным методам извне для ruby, кроме динамической диспетчеризации. Я имею в виду, что laptop.eat вызовет исключение, однако laptop.send(:eat) заставит запустить метод. Это динамическая диспетчеризация.

Что ты имеешь в виду?

zeitnot 17.02.2019 16:29

Это объясняется в документации, в спецификации языка и в самой книге по Ruby, учебнике по Ruby и курсе по Ruby.

Jörg W Mittag 17.02.2019 16:29
Ответ принят как подходящий
  • Видимость или доступ к методам и константам можно установить с помощью методы public, private или protected.
  • Ruby не позволяет вам получить доступ или изменить форму переменной экземпляра вне класса. Для преодоления этого вы должны использовать аксессуар методы
  • Приватные методы можно вызывать только внутри класса, а не из экземпляр самого класса также не используется с ключевым словом self

  • Защищенные методы могут вызываться только методами, инкапсулированными в самом классе или подклассе, а не напрямую из экземпляра класса/подкласса.

     class Machine
      attr_accessor :name,:cost
    
      # All the methods below the  protected keyword will be protected
      protected
    
      def eat
        puts "machine don't eat"
      end
    
      def sleep
        puts "machine don't sleep"
      end
    
    end
    
    machine=Machine.new
    machine.name  = "Keyword"
    puts "The name of the machine is #{machine.name}"
    
    # NoMethodError  because of accessing the protected methods via an object of Machine
    # puts machine.eat
    # puts machine.sleep
    
    class Laptop < Machine
    
      # All the method below the private keyword be will private
      private
    
      def ram                                 # private method
        return "4gb"
      end
    
      def core                                # private method
        return "i3"
      end
    
      # all the methods below the protected keyword will be protected
      public
    
      def description
        puts "The laptop has #{ram} ram and it has #{core} core"
      end
    
      def laptopActivity
        eat
        sleep
      end
    end
    
    laptop=Laptop.new
    laptop.name = "hp_notebook_15_n205tx"
    laptop.cost =44000
    
    # puts "laptop is a machine, & #{laptop.eat}"   NoMethodError coz trying to access protected method through the object
    puts "#{laptop.name} costs #{laptop.cost}"     #accessing public method of Machine through the laptop object
    puts "#{laptop.description}"                   # made description public ( description method calls private method of laptop class)
    puts laptop.laptopActivity                     # calling protected methods of parent class (inheritance)
    

Другие вопросы по теме