Шрифт:
Интервал:
Закладка:
p "Crystal".size + 4 # => 11
Это то же самое, что и более явная форма:
p("Crystal".size().+(4)) # => 11
Это показывает, что все распространенные операторы и свойства — это просто вызовы методов.
Некоторые классы не имеют буквального представления, и объекты необходимо создавать непосредственно с использованием имени класса. Ниже приведен пример:
file = File.new("some_file.txt")
puts file.gets_to_end
file.close
Здесь file — это объект типа File, показывающий, как можно открыть файл, прочитать все его содержимое, а затем закрыть его. Новый метод вызывается в File для создания нового экземпляра класса. Этот метод получает строку в качестве аргумента и возвращает новый объект File, открывая указанный файл. Отсюда внутренняя реализация этого файла в памяти скрыта и взаимодействовать с ним можно только вызовом других методов. get_to_end затем используется для получения содержимого файла в виде строки, а метод close используется для закрытия файла и освобождения некоторых ресурсов.
Предыдущий пример можно упростить, используя вариант блока, который автоматически закрывает файл после его использования:
File.openCsome_file.txt") do |file|
puts file.gets_to_end
end
В предыдущем фрагменте методу open передается блок, который получает в качестве аргумента файл (тот же, который возвращает new). Блок выполняется, а затем файл закрывается.
Возможно, вы заметили, что так же, как этот код вызывает метод gets_to_end объекта file, он также вызывает метод open класса File. Ранее вы узнали, что методы — это то, как мы общаемся с объектами, так почему же они используются и для взаимодействия с классом? Это очень важная деталь, о которой следует помнить: в Crystal все является объектами, даже классы. Все классы являются объектами типа Class, и их можно присваивать переменным точно так же, как простые значения:
p 23.class # => Int32
p Int32.class # => Class
num = 10
type = Int32
p num.class == type # => true
p File.new("some_file.txt") # => #<File:some_file.txt>
file_class = File
p file_class.newCsome_file.txt") # => #<File:some_file.txt>
Теперь вы знаете, что примитивные значения — это объекты, экземпляры более сложных типов из классов стандартной библиотеки — это объекты, и что сами классы тоже являются объектами. Каждый объект имеет внутреннее состояние и раскрывает методы мышления поведения. Переменные используются для хранения этих объектов.
Хотя Crystal поставляется со многими полезными классами, и вы можете установить больше из внешних зависимостей, вы можете создавать свои собственные классы для всего, что вам нужно. Мы рассмотрим это в следующем разделе.
Создание собственных классов
Классы описывают поведение объектов. Приятно узнать, что стандартные типы, поставляемые с Crystal, по большей части представляют собой обычные классы, которые вы могли бы реализовать самостоятельно. Кроме того, вашему приложению понадобятся еще несколько специализированных классов, поэтому давайте их создадим.
Новые классы создаются с помощью ключевого слова class, за которым следует имя, а затем определение класса. Следующий минимальный пример:
class Person
end
person1 = Person.new
person2 = Person.new
В этом примере создается новый класс с именем Person, а затем два экземпляра этого класса — два объекта. Этот класс пуст — он не определяет никаких методов или данных, но классы Crystal по умолчанию имеют некоторую функциональность:
p person1 # You can display any object and inspect it
p person1.to_s # Any object can be transformed into a String
p person1 == person2 # false. By default, compares by reference.
p person1.same?(person2) # Also false, same as above.
p person1.nil? # false, person1 isn't nil.
p person1.is_a?(Person) # true, person1 is an instance of Person.
Внутри класса вы можете определять методы так же, как и методы верхнего уровня. Один из таких методов особенный: метод initialize. Он вызывается всякий раз, когда создается новый объект, чтобы инициализировать его в исходное состояние. Данные, хранящиеся внутри объекта, хранятся в переменных экземпляра; они подобны локальным переменным, но они используются всеми методами класса и начинаются с символа @. Вот более полный класс Person:
class Person
def initialize(name : String)
@name = name
@age = 0
end
def age_up
@age += 1
end
def name
@name
end
def name=(new_name)
@name = new_name
end
end
Здесь мы создали более реалистичный класс Person с внутренним состоянием, состоящим из @name, String, @age и Int32. В классе есть несколько методов, которые взаимодействуют с этими данными, включая метод initialize, который создаст нового человека — ребенка.
Теперь давайте воспользуемся этим классом:
jane = Person.new("Jane Doe")
p jane # => #<Person:0x7f97ae6f3ea0 @name="Jane Doe", # @age=0>
jane.name = "Mary"
5.times { jane.age_up }
p jane # => #<Person:0x7f97ae6f3ea0 @name="Mary", @age=5>
В этом примере создается экземпляр Person путем передачи строки новому методу. Эта строка используется для инициализации объекта и в конечном итоге присваивается переменной экземпляра @name. По умолчанию объекты можно проверять с помощью метода верхнего уровня p, который показывает имя класса, адрес в памяти и значение переменных экземпляра. Следующая строка вызывает метод name=(new_name) — он может делать что угодно, но для удобства он обновляет переменную @name новым значением. Затем мы вызываем age_up пять раз и снова проверяем объект. Здесь вы должны увидеть новое имя и возраст человека.
Обратите внимание, что в методе initialize мы явно указываем тип аргумента имени вместо того, чтобы позволить компилятору определить его на основе использования. Здесь это необходимо, поскольку типы переменных экземпляра должны быть известны только из класса и не могут быть выведены из использования. Вот почему нельзя сказать, что Crystal имеет механизм вывода глобального типа.
Теперь давайте углубимся в то, как можно определять методы и переменные экземпляра.
- QT 4: программирование GUI на С++ - Жасмин Бланшет - Программирование
- C# для профессионалов. Том II - Симон Робинсон - Программирование
- Как спроектировать современный сайт - Чои Вин - Программирование
- Microsoft Visual C++ и MFC. Программирование для Windows 95 и Windows NT. Часть 2 - Александр Фролов - Программирование
- Краткое введение в программирование на Bash - Гарольд Родригес - Программирование
- Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен - Программирование
- Каждому проекту своя методология - Алистэр Коуберн - Программирование
- Разработка ядра Linux - Роберт Лав - Программирование
- Графические интерфейсы пользователя Java - Тимур Сергеевич Машнин - Программирование
- C# 4.0: полное руководство - Герберт Шилдт - Программирование