Доброго времени суток!
Появился интерес сделать не как в конспекте, и не через аргументы в скобках, - а как бы диалогом. Через gets и т.д. В случае с уроком, мы сами(!) пишем аргументы к методам. Но мы разработчики, мы можем залезть в код и написать аргументы. А хочется, чтобы эти аргументы запрашивались у пользователя (через gets) - потом усаживались на место аргументов куда надо.
Так как мы конструктор уже наследовали, сделал для класса Смартфоны метод data. Там всё запрашиваю у пользователя. Но возникла проблема как новые переменные пропустить через метод update. + он ещё и хэш. И ладно, я вроде разобрался (тем менее, пожалуйста ознакомьтесь с кодом). Но вот метод showcase не хочет забирать мои новые переменные.... (там each_with_index)
Сделал конструктор как в Уроке. Но... Конструктор надо скопировать в субкласс. Да ещё и дополнить. Вроде super, да вроде и нет =( Всё равно вываливает ошибку.
Вот весь код и картинки:
Субкласс
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)
Посмотри внимательно куда указывает ошибка:
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
И кстати в основном скрипте less72.rb
не используй вот такие @переменные — так пишутся только переменные экземпляра в классах. В основном коде используй обычные переменные.
PS:
ты достаточно хорошо описал текстом и ошибку и код приложил, в таком раскладе не нужно скриншотов и много текстом описывать. Обычно код и скопированное полное сообщение об ошибке или исключении (или лог файл) говорят сами за себя.
Спасибо, Миш, за ответ! Самое прикольное, что...или ты меня вчера мысленно отругал немного =)) Или реально был не мой день + усталость, может быть.
Спокойно сел, отменил всё-всё до того момента, когда код работал. То есть, до всех моих нововведений. Критично глянул....немного поправил....и всё завелось!!! По большей части... ну, хотя бы успешно всё было, как минимум.
Аргументы "супера"....?:о Ок, посмотрю этот момент внимательно. Спасибо!
Погоди. А как(!) тогда аргументы для методов можно передавать от пользователя? Мы не будем вечность записывать их как аргументы. Они же должны откуда-то браться, кем-то вводиться... Какими способами можно решить эту задачу? Спрашиваю сугубо профессионально!)
Передавать аргументами это стандартный вариант для большинства случаев. Пока не пытайся узнать сразу все случаи, разберем еще не раз эту тему.
Главное что сейчас надо понять — один класс в идеале должен заниматься одной группой задач и представлять какую-то одну самостоятельную сущность. Например класс продукта должен хранить и может рассчитывать информацию о продукте.
А ввод информации это уже другой вид задач, потому что ввод может быть очень разный (из файлов, из консоли, из веб сервиса, из голубиной почты...)
На простых примерах это не так наглядно, поэтому сильно не углубляйся, иди дальше.