Ruby - это объектно-ориентированный язык программирования.

А теперь для непосвященных начнем с самого начала. Чтобы понять концепцию класса, давайте возьмем пример реального физического объекта, собаки, которая будет представлять класс. Может быть много собак с одинаковым поведением (или состояниями). Теперь вы можете взять конкретно одну собаку, скажем Томми

tommy = Dog.new(“tommy”)

Теперь tommy - это экземпляр или объект класса Dog, потому что он имеет все поведения этого класса. У собаки 5 возможных вариантов поведения: есть, спать, гулять, кусаться и гавкать. У него также есть функциональность, которая позволяет вам изменять его состояние, вы можете кормить его, чтобы он ел.

Объектно-ориентированное программирование (ООП) - это парадигма программирования, которая позволяет управлять объектом с помощью методов. Вы можете изменить состояние объекта, выполнив над ним определенные действия. Вы можете назвать эти действия методом. Есть несколько основных концепций программирования OOPS:

Инкапсуляция

Скажем, для общения с Томми у нас есть 5 команд или, в терминах Ruby, методы, теперь Томми может есть (), спать (), ходить (), укусить () и говорить (). Теперь, если есть еще одна собака, Софи, она также может иметь доступ ко всем этим 5 методам независимо от Томми. Софи и Томми могут вести себя по-разному в любой момент времени.

Инкапсуляция достигается, когда каждый объект сохраняет свое состояние закрытым внутри класса. Другие объекты не имеют прямого доступа к этому состоянию. Вместо этого они могут вызывать только список общедоступных функций, называемых методами.

Таким образом, объект управляет своим собственным состоянием с помощью методов - и никакой другой класс не может прикоснуться к нему, если это явно не разрешено. Если вы хотите общаться с объектом, вы должны использовать предоставленные методы. Но (по умолчанию) вы не можете изменить состояние. Итак, если у нас есть другой класс с именем Cat, он не будет иметь доступа к Tommy, поскольку в Tommy не может «мяукать», потому что tommy является экземпляром класса Dog.

Обычно инкапсуляция достигается за счет контроля доступа. Эти три метода используются в Ruby для управления доступом: частный, защищенный и общедоступный.

Наследование

Наследование - это способность связанных классов разделять поведение через иерархическую структуру единственного наследования. Подклассы наследуют методы от своих родительских классов. Это называется одиночным наследованием, потому что данный класс может напрямую наследовать только от одного родительского класса. В нашем примере давайте добавим еще один класс с именем Animal, который будет нашим суперклассом . За счет создания подклассов классов cat и Dog от этого общего предка Animal оба этих подкласса будут унаследовать поведение и атрибут Animalclass.

class Animal
  def eat(food = "grass")
    puts "I eat #{food}"
  end
  def walk
   puts "I am walking"
  end
end
class Dog < Animal
  attr_accessor :name
  def initialize(name = "doggo")
    @name = name
  end
  def eat(food = "kibbles")
    super
  end 
  def speak 
    "woof"
  end 
end
class Cat < Animal
  attr_accessor :name
  def initialize(name = "canto")
    @name = name
  end
  def eat(food = "fishy")
    super
  end 
  def speak
    "meow"
  end
end
tommy = Dog.new("Tommy")
# this line is initialising a new object of class dog, note the object will have properties of both Dog and Animal class, since Dog is inheriting Animal.
tommy.walk # this will return "I am walking"
# this will change the state of object tommy as walking. Also, walk is the superclass method, all the Animals can walk, since Dog is inheriting from Animals it can also walk.
tommy.eat
# this will change the state of object tommy as eating. Notice we hadn't passed any argument to method eat because we have set the default argument as "kibbles". 
Tommy.eat("chimken")
# now tommy is eating chimken, yomyom, okay so now we have over ride the default argument, hence tommy now gets to eat chimken. Also the method is using a keyword called super.
kitty = Cat.new("kitty") 
# this line is initialising a new object of class Cat, note the object will have properties of both Cat and Animal class, since Cat is inheriting Animal.
Note: name would be the attribute of class Dog. It would be unique for each object. There are two concepts here, attribute and behaviour, attributes would be instance_variables because they are uniq to each object and behaviours would be your methods.

Полиморфизм

Полиморфизм состоит из двух слов Поли, что означает Многие и Морф, что означает Формы. В Ruby это означает возможность отправлять одно и то же сообщение разным объектам и получать разные результаты. Давайте рассмотрим несколько разных способов добиться этого.

Полиморфизм с использованием наследования

Из нашего предыдущего примера, если мы определили метод с именем eat в нашем родительском классе Animal, который мы снова используем в нашем дочернем классе Dog. Обратите внимание на использование ключевого слова super в нашем дочернем классе. Использование ключевого слова super означает, что когда метод с аргументами переопределяется одним из его дочерних классов, тогда вызов super без каких-либо аргументов в дочернем методе автоматически передаст аргументы дочернего метода родительскому методу.

Полиморфизм с использованием Duck-Typing

Duck Typing - забавная идея. Как сказал Джеймс Уиткомб Райли:

Когда я вижу птицу, которая ходит, как утка, плавает, как утка, и крякает, как утка, я называю эту птицу уткой.

Вместо того, чтобы проверять, принадлежит ли объект определенному типу, все, что нас беспокоит, - это то, что объект может отвечать на вызов метода в определенном контексте. Таким образом, в нашем предыдущем примере tommy будет woof, если мы вызовем speak, а kitty meow.

Абстракция

Абстракцию можно рассматривать как естественное расширение инкапсуляции. Применение абстракции означает, что каждый объект должен только предоставлять высокоуровневый механизм для его использования. Этот механизм должен скрывать детали внутренней реализации. Он должен раскрывать только операции, относящиеся к другим объектам. Желательно, чтобы этот механизм был простым в использовании и редко менялся с течением времени. Думайте об этом как о небольшом наборе общедоступных методов, которые любой другой класс может вызывать, не «зная», как они работают.

ПОНИМАНИЕ ЭКСПЕРТИЗА И МЕТОДОВ КЛАССА

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

class Example
  def self.class_method
    instance_method # It will throw NoMethodError
  end
  def instance_method
    # some data
  end
end

Итак, почему он выдал ошибку, определенно существует метод с именем instance_method. Что тут происходит? На самом деле ruby ​​ищет метод класса, потому что ruby ​​будет читать его как self.instance_method Здесь self - это сам «класс», отсюда и ошибка. Имейте в виду, что методы класса не имеют доступа к методам экземпляра или переменным экземпляра. Однако методы экземпляра могут обращаться как к методам класса, так и к переменным класса.