Урок 7. Пытаемся делать по своему....

[М] Михаил Беркович, 15 ноября 2018, 20:27 , 2 подписчика

Доброго времени суток!

Появился интерес сделать не как в конспекте, и не через аргументы в скобках, - а как бы диалогом. Через gets и т.д. В случае с уроком, мы сами(!) пишем аргументы к методам. Но мы разработчики, мы можем залезть в код и написать аргументы. А хочется, чтобы эти аргументы запрашивались у пользователя (через gets) - потом усаживались на место аргументов куда надо.

Так как мы конструктор уже наследовали, сделал для класса Смартфоны метод data. Там всё запрашиваю у пользователя. Но возникла проблема как новые переменные пропустить через метод update. + он ещё и хэш. И ладно, я вроде разобрался (тем менее, пожалуйста ознакомьтесь с кодом). Но вот метод showcase не хочет забирать мои новые переменные.... (там each_with_index)

Сделал конструктор как в Уроке. Но... Конструктор надо скопировать в субкласс. Да ещё и дополнить. Вроде super, да вроде и нет =( Всё равно вываливает ошибку.

Вот весь код и картинки: enter image description here

Субкласс

class Smarts < Product

  attr_accessor :vendor, :model

  def initialize(vendor, model)
    super
    @vendor = vendor
    @model = model
  end
  def data

  end

  def update(options)
    @vendor = options[:vendor]
    @model = options[:model]
  end

  def info
    "Фирма #{@vendor} выпустила новую модель - #{@model}"
  end
end

Суперлкласс:

class Product
  def initialize
    puts "Введите цену товара..."
    price = STDIN.gets.chomp.to_i
    @price = price
    puts "Сколько осталось экземпляров на складе..."
    how_many = STDIN.gets.chomp.to_i
    @how_many = how_many
  end

  def price
    @price
  end

  def update
  end

  def info
  end

  def show
    puts "#{info} - #{@price} руб. [осталось: #{@how_many}]"
  end

  def self.showcase(products)
    puts "Что хотите купить?\n\n"

    products.each_with_index do |product, index|
      puts "#{index}: #{product.show}"
    end

    puts "\n"
  end

   def cls
     system "clear" or system "cls"
   end
end

Тут метод cls выдаёт ошибку...

C:/Rubyless2/less7/less71(-4)/less72.rb:36:in `<main>': undefined local variable or method `cls' for main:Object (NameError)
Did you mean?  class

Главный файл.

if (Gem.win_platform?)
  Encoding.default_external = Encoding.find(Encoding.locale_charmap)
  Encoding.default_internal = __ENCODING__

  [STDIN, STDOUT].each do |io|
    io.set_encoding(Encoding.default_external, Encoding.default_internal)
  end
end

require_relative './product.rb'
require_relative './books.rb'
require_relative './music.rb'
require_relative './films.rb'
require_relative './smarts.rb'

products = []
 product = Films.new
 product.update(:name => 'Леон', :director => 'Люк Бессон', :year => 1994)
 products.push(product)

 product = Music.new
 product.update(:album => 'Metallica(Black Album)', :singer => 'Metallica', :date => 1991, :genre => "Thrash Metal")
 products.push(product)

 product = Books.new
 product.update(:author => 'Стивен Кинг', :named => 'Оно')
 products.push(product)


puts "Введите информацию о телефоне" #наверно - это лучше вынести в Initialize метода smarts.rb
puts "Производитель: "
@vendor = STDIN.gets.chomp.to_s
puts "Модель: "
@model = STDIN.gets.chomp.to_s
cls
product = Smarts.new(@vendor, @model)
# product.data
product.update(:vendor => @vendor, :model => @model)
products.push(product)

Product.showcase(products)
  • 7-14.rar Весь код - вот сюда!

Обсуждение (4)


Michael Butlitsky Учитель

[M]

  • cls

Посмотри внимательно куда указывает ошибка:

C:/Rubyless2/less7/less71(-4)/less72.rb:36:in `<main>': undefined local variable or method `cls' for main:Object (NameError)
Did you mean?  class

В файле less72.rb на 36 строке странная команда cls, руби такой не знает. Сравни с тем что мы делаем в своем коде (там команда system("cls")), изучи что делает system: https://ruby-doc.org/core-2.2.0/Kernel.html#method-i-system

  • Причина ошибки с родительским классом в этом месте:
def initialize(vendor, model)
    super
    @vendor = vendor
    @model = model
end

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

Вот так заработает (ты явно указал что вызываешь родительский метод с пустыми параметрами):

def initialize(vendor, model)
    super()
    @vendor = vendor
    @model = model
end
  • Гораздо лучше будет вообще избавить все классы (и родительский) от gets и передавать все данные как аргументы в конструктор.

И кстати в основном скрипте less72.rb не используй вот такие @переменные — так пишутся только переменные экземпляра в классах. В основном коде используй обычные переменные.

PS:
ты достаточно хорошо описал текстом и ошибку и код приложил, в таком раскладе не нужно скриншотов и много текстом описывать. Обычно код и скопированное полное сообщение об ошибке или исключении (или лог файл) говорят сами за себя.


Михаил Беркович

[М]

Спасибо, Миш, за ответ! Самое прикольное, что...или ты меня вчера мысленно отругал немного =)) Или реально был не мой день + усталость, может быть.

Спокойно сел, отменил всё-всё до того момента, когда код работал. То есть, до всех моих нововведений. Критично глянул....немного поправил....и всё завелось!!! По большей части... ну, хотя бы успешно всё было, как минимум.

Аргументы "супера"....?:о Ок, посмотрю этот момент внимательно. Спасибо!

Погоди. А как(!) тогда аргументы для методов можно передавать от пользователя? Мы не будем вечность записывать их как аргументы. Они же должны откуда-то браться, кем-то вводиться... Какими способами можно решить эту задачу? Спрашиваю сугубо профессионально!)


Michael Butlitsky Учитель

[M]

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

Главное что сейчас надо понять — один класс в идеале должен заниматься одной группой задач и представлять какую-то одну самостоятельную сущность. Например класс продукта должен хранить и может рассчитывать информацию о продукте.

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

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


Михаил Беркович

[М]

Спасибо за разъяснение. Оставлю. Само потом впитается, да и будет много задач, где будет ООП. Рука поднабьётся ещё! А пока...пилю запись XMLек...