Поиск…


Синтаксис

  • имя класса
  • # некоторый код, описывающий поведение класса
  • конец

замечания

Названия классов в Ruby - это константы, поэтому первая буква должна быть капиталом.

class Cat # correct
end  

class dog # wrong, throws an error
end

Создание класса

Вы можете определить новый класс, используя ключевое слово class .

class MyClass
end

После определения вы можете создать новый экземпляр, используя метод .new

somevar = MyClass.new
# => #<MyClass:0x007fe2b8aa4a18>

Конструктор

Класс может иметь только один конструктор, то есть метод, называемый initialize . Метод автоматически вызывается, когда создается новый экземпляр класса.

class Customer
  def initialize(name)
     @name = name.capitalize 
  end
end

sarah = Customer.new('sarah')
sarah.name #=> 'Sarah'

Переменные класса и экземпляра

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

Переменные экземпляра, которым предшествует @ . Они полезны, если вы хотите использовать одну и ту же переменную в разных методах.

class Person
  def initialize(name, age)
    my_age = age # local variable, will be destroyed at end of constructor
    @name = name # instance variable, is only destroyed when the object is
  end

  def some_method
    puts "My name is #{@name}." # we can use @name with no problem
  end
   
  def another_method
    puts "My age is #{my_age}." # this will not work!
  end
end

mhmd = Person.new("Mark", 23)

mhmd.some_method #=> My name is Mark.
mhmd.another_method #=> throws an error

Переменная класса, которой предшествует @@ . Они содержат одинаковые значения во всех экземплярах класса.

class Person
  @@persons_created = 0 # class variable, available to all objects of this class
  def initialize(name)
    @name = name

    # modification of class variable persists across all objects of this class
    @@persons_created += 1
  end  
      
  def how_many_persons
    puts "persons created so far: #{@@persons_created}"
  end 
end
    
mark = Person.new("Mark")
mark.how_many_persons #=> persons created so far: 1
helen = Person.new("Helen")

mark.how_many_persons #=> persons created so far: 2
helen.how_many_persons #=> persons created so far: 2
# you could either ask mark or helen

Глобальные переменные, которым предшествует $ . Они доступны в любом месте программы, поэтому обязательно используйте их с умом.

$total_animals = 0

class Cat
  def initialize
    $total_animals += 1
  end
end

class Dog
  def initialize
    $total_animals += 1
  end
end

bob = Cat.new()
puts $total_animals #=> 1
fred = Dog.new()
puts $total_animals #=> 2

Доступ к переменным экземпляра с помощью геттеров и сеттеров

У нас есть три метода:

  1. attr_reader : используется для read переменной вне класса.
  2. attr_writer : используется для модификации переменной вне класса.
  3. attr_accessor : объединяет оба метода.
class Cat
  attr_reader :age # you can read the age but you can never change it
  attr_writer :name # you can change name but you are not allowed to read
  attr_accessor :breed # you can both change the breed and read it

  def initialize(name, breed)
    @name = name
    @breed = breed
    @age = 2 
  end
  def speak
    puts "I'm #{@name} and I am a #{@breed} cat"
  end
end
 
my_cat = Cat.new("Banjo", "birman")
# reading values:

my_cat.age  #=> 2
my_cat.breed #=> "birman"
my_cat.name #=> Error

# changing values
 
my_cat.age = 3 #=> Error
my_cat.breed = "sphynx" 
my_cat.name = "Bilbo"

my_cat.speak #=> I'm Bilbo and I am a sphynx cat

Обратите внимание, что параметры являются символами. это работает путем создания метода.

class Cat
  attr_accessor :breed
end

В основном это то же самое, что:

class Cat
  def breed
    @breed
  end
  def breed= value
    @breed = value
  end
end

Уровни доступа

Ruby имеет три уровня доступа. Они являются public , private и protected .

Методы, которые следуют за private или protected ключевыми словами, определяются как таковые. Методы, которые появляются перед ними, являются неявно public методами.

Общественные методы

Открытый метод должен описывать поведение создаваемого объекта. Эти методы можно вызывать из-за пределов созданного объекта.

class Cat
  def initialize(name)
    @name = name
  end

  def speak
    puts "I'm #{@name} and I'm 2 years old"
  end
  
  ...
end

new_cat = Cat.new("garfield")
#=> <Cat:0x2321868 @name="garfield">
 
new_cat.speak
#=> I'm garfield and I'm 2 years old

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

public ключевое слово не нужно, но может использоваться для выхода из private или protected

def MyClass
  def first_public_method
  end

  private

  def private_method
  end

  public

  def second_public_method
  end
end

Частные методы

Частные методы недоступны извне объекта. Они используются внутри объекта. Повторное использование примера cat:

class Cat
  def initialize(name)
    @name = name
  end

  def speak
    age = calculate_cat_age # here we call the private method 
    puts "I'm #{@name} and I'm #{age} years old"
  end

  private
     def calculate_cat_age
       2 * 3 - 4 
     end
end

my_cat = Cat.new("Bilbo")
my_cat.speak #=> I'm Bilbo and I'm 2 years old
my_cat.calculate_cat_age #=> NoMethodError: private method `calculate_cat_age' called for #<Cat:0x2321868 @name="Bilbo">

Как вы можете видеть в приведенном выше примере, только что созданный объект Cat имеет доступ к методу calculate_cat_age внутри. Мы присваиваем переменный age в результате запуска частного calculate_cat_age метода , который печатает имя и возраст кошки на консоль.

Когда мы пытаемся вызвать метод calculate_cat_age извне объекта my_cat , мы получаем NoMethodError потому что он частный. Возьми?

Защищенные методы

Защищенные методы очень похожи на частные методы. Они не могут быть доступны вне экземпляра объекта так же, как частные методы не могут быть. Однако, используя метод self ruby, защищенные методы могут быть вызваны в контексте объекта того же типа.

class Cat
  def initialize(name, age)
    @name = name
    @age = age
  end

  def speak
    puts "I'm #{@name} and I'm #{@age} years old"
  end

  # this == method allows us to compare two objects own ages. 
  # if both Cat's have the same age they will be considered equal.
  def ==(other)
     self.own_age == other.own_age
  end

  protected
     def own_age
        self.age
     end
end

cat1 = Cat.new("ricky", 2)
=> #<Cat:0x007fe2b8aa4a18 @name="ricky", @age=2>

cat2 = Cat.new("lucy", 4)
=> #<Cat:0x008gfb7aa6v67 @name="lucy", @age=4>

cat3 = Cat.new("felix", 2)
=> #<Cat:0x009frbaa8V76 @name="felix", @age=2>

Вы можете видеть, что мы добавили параметр возраста в класс cat и создали три новых объекта кошки с именем и возрастом. Мы будем называть метод own_age чтобы сравнить возраст наших объектов кошки.

cat1 == cat2
=> false

cat1 == cat3
=> true

Посмотрите на это, мы смогли восстановить возраст cat1 с помощью метода self.own_age protected и сравнить его с возрастом cat2, вызвав cat2.own_age внутри cat1.

Типы типов классов

Классы имеют 3 типа методов: instance, singleton и class.

Методы экземпляра

Это методы, которые можно вызывать из instance класса.

class Thing
  def somemethod
    puts "something"
  end
end

foo = Thing.new # create an instance of the class
foo.somemethod # => something

Метод класса

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

class Thing
  def Thing.hello(name)
    puts "Hello, #{name}!"
  end
end

Это эквивалентно использованию self вместо имени класса. Следующий код эквивалентен приведенному выше коду:

class Thing
  def self.hello(name)
    puts "Hello, #{name}!"
  end
end

Вызовите метод, написав

Thing.hello("John Doe")  # prints: "Hello, John Doe!"

Методы Singleton

Они доступны только для определенных экземпляров класса, но не для всех.

# create an empty class
class Thing
end

# two instances of the class
thing1 = Thing.new
thing2 = Thing.new

# create a singleton method
def thing1.makestuff
  puts "I belong to thing one"
end

thing1.makestuff # => prints: I belong to thing one
thing2.makestuff # NoMethodError: undefined method `makestuff' for #<Thing>

Оба метода singleton и class называются eigenclass es. В основном, что Ruby делает, это создать анонимный класс, который содержит такие методы, чтобы он не мешал созданным экземплярам.

Другой способ сделать это - конструктор class << . Например:

# a class method (same as the above example)
class Thing
  class << self # the anonymous class
    def hello(name)
      puts "Hello, #{name}!"
    end
  end
end

Thing.hello("sarah") # => Hello, sarah!

# singleton method

class Thing
end

thing1 = Thing.new

class << thing1
  def makestuff
    puts "I belong to thing one"
  end
end

thing1.makestuff # => prints: "I belong to thing one"

Создание динамического класса

Классы могут создаваться динамически с помощью Class.new .

# create a new class dynamically
MyClass = Class.new

# instantiate an object of type MyClass
my_class = MyClass.new

В приведенном выше примере создается новый класс и назначается константе MyClass . Этот класс может быть создан и использован как любой другой класс.

Метод Class.new принимает Class который станет суперклассом динамически созданного класса.

# dynamically create a class that subclasses another
Staffy = Class.new(Dog)

# instantiate an object of type Staffy
lucky = Staffy.new
lucky.is_a?(Staffy) # true
lucky.is_a?(Dog)    # true

Метод Class.new также принимает блок. Контекст блока - это новый класс. Это позволяет определять методы.

Duck = 
  Class.new do
    def quack
      'Quack!!'
    end
  end

# instantiate an object of type Duck
duck = Duck.new
duck.quack # 'Quack!!'

Создать, выделить и инициализировать

На многих языках новые экземпляры класса создаются с использованием специального new ключевого слова. В Ruby new также используется для создания экземпляров класса, но это не ключевое слово; вместо этого это метод static / class, отличный от любого другого метода static / class. Это примерно так:

class MyClass
   def self.new(*args)
     obj = allocate
     obj.initialize(*args) # oversimplied; initialize is actually private
     obj
   end
end

allocate выполняет реальную «магию» создания неинициализированного экземпляра класса

Также обратите внимание, что возвращаемое значение initialize отбрасывается, и вместо него возвращается obj. Это сразу позволяет понять, почему вы можете кодировать свой метод инициализации, не беспокоясь о возврате self в конце.

«Обычный» new метод, который все классы получают из Class работает, как описано выше, но можно переопределить его, как вам нравится, или определить альтернативы, которые работают по-другому. Например:

class MyClass
  def self.extraNew(*args)
    obj = allocate
    obj.pre_initialize(:foo)
    obj.initialize(*args)
    obj.post_initialize(:bar)
    obj
  end
end


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow