Рубрики
Лекции mail.ru Лекция 4

Лекция 4. Языки веб-программирования. Ruby: Классы, Модули, Примеси


Таймкоды
4:12 — описание работы инструмента jupyter
7:30 — особенности передачи параметров в методы
13:45 — классы
14:21 — именование переменных
14:51 — разбор программы, выводящей связь предок-потомок в древеобразной форме
20:52 — конструкторы
24:41 — атрибуты
30:50 — пространство объектов
32:44 — класс Struct
34:59 — наследование
36:02 — доступ к метаданным
38:01 — управление доступом
42:44 — «замораживание» объекта методом freeze
45:14 — константы
48:04 — распределенное объявление и переопределение классов
53:03 — видимость атрибутов
57:18 — определение методов на русском языке
58:21 — класс Module
1:00:41 — примеси (mixins)
1:04:10 — сравнение Enumerator и Enumerable
1:06:33 — класс Enumerator
1:12:18 — класс Enumerable
1:14:37 — динамическое выполнение кода
1:18:22 — тестирование через построение дерева
1:20:27 — тестирование с помощью тестовых наборов
1:21:37 — автоматические тесты
1:26:44 — отладка Ruby-программ
1:29:48 — статическая проверка кода
1:32:39 — Ruby Version Manager (RVM)

Параметры

*x — как параметр обозначает не ограниченное кол-во аргументов
**x — не ограниченное кол-во аргументов, но для ключевого слова аргументов. Будет хеш вместо массива

def testing(a, b = 1, *c, d: 1, **x)
  p a,b,c,d,x
end

testing('a', 'b', 'c', 'd', 'e', d: 2, x: 1)Code language: JavaScript (javascript)
  • * — как параметр обозначает взять все аргументы
def print_all(*)
end

Это означает, что метод принимает любые аргументы, но ничего с ними не делает. Это похоже на использование символа подчеркивания (_) внутри блока, чтобы показать, какие аргументы вы не используете.

На практике это может быть в сочетании с ключевым словом super:

class Food
  def nutrition(vitamins, minerals)
    puts vitamins
    puts minerals
  end
end
class Bacon < Food
  def nutrition(*)
    super
  end
end
bacon = Bacon.newCode language: JavaScript (javascript)

Проверка сцепленных опператоров. Save navigation operator(&.)

После руби 2.3

if account&.owner&.address
  ...
endCode language: CSS (css)

Классы

class Color
  def initialize(r,g,b,s1,s2)
    @r, @g, @b, @s1, @s2 = r,g,b,s1,s2
  end

  def self.while(s1,s2)
    new(000, 000, 000, s1, s2) # Указали первые 3 значения для конструктора. И перезаписали метод new
  end

  def inspect
    "#{@r}, #{@g}, #{@b}, #{@s1}, #{@s2}" # Презаписали вывод для 'p' в более удобный вид
  end
end

b = Color.while(13,234)

p b

# 0, 0, 0, 13, 234
Code language: CSS (css)
class Metal
  @@current_temp = 70
  attr_accessor :atomic_number

  def Metal.current_temp=(x)
    @@current_temp = x
  end

  def Metal.current_temp
    @@current_temp
  end

  def liquid?
    @@current_temp >= @melting
  end

  def initialize(atnim, melt)
    @atomic_number = atnim
    @melting = melt
  end

end

alum = Metal.new(60, 1340)
gold = Metal.new(79, 1984)

p alum.liquid?
p gold.liquid?
Metal.current_temp = 1982
p alum.liquid?
p gold.liquid?

# false
# false
# true
# falseCode language: CSS (css)

Класс Struct

Применяется для сокращения записи при создании класса
attr_reader с атрибутами объявляется не явно

Student = Struct.new(:fname, :name)
stud = Student.new("Pavel", "Pestau")

p Student.class
p stud.class 
puts "Студ #{stud.fname} #{stud.name}"Code language: Ruby (ruby)

Управление доступом в классе

  • Public — общедоступные методы (можем не писать)
  • Protected — только для класса и потомков
  • Private — только для методов класса

Внимание! Мы можем ограничивать доступ не только для методов но и для аттрибутов, например программа которая сравнивает возраст пользователей, не позволяет прочитать его (возраст)

class Person
  def initialize(name, age)
    @name, @age = name, age
  end
  def <=> (other)
    age <=> other.age
  end
  attr_reader :name, :age # Определяем аттрибуты
  protected :age # закроем возраст для доступа
end

p1 = Person.new('Fred', 31)
p2 = Person.new('Max', 20)

p (p1 <=> p2) # 1
p p2.age # protected method `age' called for #<Person:0x0Code language: Ruby (ruby)

Freeze. Особенности работы

Есть строка, применили freeze и добавили сложение с другой строкой, по идее значение переменной не должно меняться, однако оно измениться.

На самом деле мы не изменили объект, а создали ссылку на новый и присвоили ее нашей переменной.

Что же делать? — Использовать константы. Константа позволяет заблокировать изменение ссылки в переменной на который она ссылается. Теперь если мы применим freeze все будет работать

Переопределение методов в стандартных классах

class Time
  def to_s
    strftime '%H:%M:%S %d.%m'
  end
  def inspect 
    print "Метод инспект был перезаписан"
  end
end

puts Time.now
p Time.now

# 16:46:40 01.09
# Метод иснпект был перезаписанCode language: Ruby (ruby)

Выполнение кода из строки и из внешнего файла методами Eval и load(‘file.rb’, true)

Тестировние дерева

class Tree
  attr_accessor :left, :right, :data 
  protected :left, :right, :data
  
  def initialize(x = nil)
    @left, @right, @data = nil, nil, x
  end

  def insert(x)
    if @data.nil? 
      @data = x
    elsif x <= @data
      @left ? @left.insert(x) : @left = Tree.new(x)
    else
      @right ? @right.insert(x) : @right = Tree.new(x)
    end 
  end
  def inorder
    @left.inorder { |y| yield y } unless @left.nil? 
      yield @data
    @right.inorder { |y| yield y } unless @right.nil?
  end
  
  def inbackorder
  @right.inbackorder { |y| yield y } unless @right.nil? 
    yield @data
  @left.inbackorder { |y| yield y } unless @left.nil?
  end 
end




items = [1,5,6,3,2,8,7,4,9]
# или items = gets.split.map(&:to_i)
# или items = Array.new(14){ rand(100)-50 }
tree = Tree.new
items.each { |x| tree.insert(x) }
puts tree.inorder { |x| print "#{x} "} 
puts tree.inbackorder { |x| print "#{x} "}Code language: Ruby (ruby)
require './z.rb' # Путь к файлу
require 'minitest/autorun'
class TestTree < MiniTest::Unit::TestCase
  def setup # вызывается перед выполнением каждого теста
    #@items = [35, 1, 24, 2, -4, 3, 25, 4, 94, 5, 0, 6, 14, 7]
    @items = Array.new(100) { rand(200) - 100 }
    #@items = 100.times.map { Random.rand(200) - 100 }
    @tree = Tree.new
    @items.each { |x| @tree.insert(x) } 
    @result = [ ]
  end
  def test_1
    @tree.inorder { |x| print "#{x} "; @result << x } # формируем результат assert_equal(@items.sort, @result) # сравниваем c эталоном
  end
  def test_2
    @tree.inbackorder { |x| print "#{x} "; @result << x } # формируем результат assert_equal(@items.sort_by { |x| -x }, @result ) # сравниваем c эталоном
  end
endCode language: Ruby (ruby)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *