Папярэдні занятак

Што такое Хэш

Перад тым як мы пойдзем далей, давайце разглядзім яшчэ адзін тым аб’ектаў Рубі – (хэшы) hashes.

Хэшы выглядаюць як тэлефоныя кнігі. Паспрабуйце выканаць гэта ў кансолі:

  • phones = {"Elizabeth" => 4155551212, "Robert" => 6505551212, "Christopher" => 5105551212}
  • phones["Elizabeth"]

Гэта нешта накшталт масіваў, але замест таго, каб карыстацца лікавым індэксам каб зьвярнуцца да элемэнта, мы карыстаемся ключом (key) каб вымаць значэньне (value).

Код => завецца hash rocket; ключ злева, а значэньне справа.

Вы можаце зьмяніць значэньні ва існуючым хэшэ:

  • phones["Elizabeth"] = 3105551212
  • phones

Адна рэч, якую варта запомніць пра хэшы, гэта, што яны ў адрозьнене ад масіваў, не захоўваюць свае элемэнты ў якім-небудзь канкрэтным парадку.

Стварыце хэш з нікнэймамі Вашых сяброў у якасьці ключоў і іхнымі сапраўднымі імёнамі ў якасьці значэньняў.

Стварыце хэш, з назвамі страў і іх коштамі ў кавярне. Потым выкарыстайце мэтад each каб зрабіць зніжку 20% на кожную страву.

Самі адшукайце дакумэнтацыю Ruby па хэшам і праглядзіце якія яшчэ мэтады ёсьць для іх.

Вызначэньне класа

Зараз мы знаходзімся ў кропке, калі прыйшоў час вярнуцца назад і паспрабаваць зразумець вялікую карціну.

Мы ўжо пазнаёміліся з наступнымі тыпамі ў Ruby: integers, floats, strings, arrays, і hashes. Кожны з гэтых тыпаў мы завем класам (class).

Кожны кантрэктны аб’ект (напрыклад: лік 1, дробны лік -0.36, радок "I am radok", масіў – ["big", "array", 42], хэш – {"a" => 13} і г.д.) мы завем асобнікам (instance) класа.

Калі Вы хацелі даведацца якога класа які-небудзь аб’ект; вось як гэта зрабіць:

  • 1.23.class
  • "hello".class
  • [1,2,3,2,1].class
  • (1..5).class
  • {"key" => "value"}.class
  • nil.class

Назвы класаў пачынаюцца з вялікай літары. Калі імя класа мае некалькі словаў (напрыклад NilClass), традыцыйна кожнае слова пішыцца з вялікай літары. Гэта завецца стыль вярблюда (upper camel case), таму што крыху нагадвае гарбы вярблюда :).

Мета класы?

  • Float.class
  • String.class
  • Array.class
  • Range.class
  • Hash.class

І яшчэ больш мета:

  • Class.class

Спадкаваньне

Паспрабуйце:

  • 5.class
  • 53478290674382906753829067528923506.class

З дакумэнтацыі Ruby: “Fixnum можа трымаць цэлыя значэньні якія могуць быць прадстаўлены ў адным машыным слове (мінус 1 біт). Калі значэньне перавышае гэты дыяпазон, значэньне канвэртуецца ў Bignum”. Іншымі словамі, маленькія цэлыя лікі – гэта Fixnum, вялікія цэлыя лікі – гэта Bignum.

Паспрабуйце гэта:

  • 1.class.superclass
  • 154676457623465471324636734262573564.class.superclass

Fixnum і Bignum успадкоўваюцца ад класа Integer.

Вы можаце стварыць свой клас, які будзе мець усе ўласьцівасьці іншага (суперкласа – бацькі):

  • class AwesomeArray < Array
  • # Awesome stuff goes here
  • end

Зараз усе мэтады, якія мае Array даступны ў AwesomeArray. Гэта завецца спадкаваньне.

Вы можаце даведаццца ад каго ўспадкоўваецца які-небудзь клас мэтадам superclass:

  • AwesomeArray.superclass

Калі Вы ствараеце новы клас, па-дэфолту ён успадкоўваецца ад Object. Даведайцеся ад каго ўспадкоўваецца Object.

Вы можаце даведацца пра ўсе класы, ад які ўспадкоўваецца Ваш клас выкарыстоўваючы мэтад ancestors:

  • AwesomeArray.ancestors

Паспрабуйце мэтад ancestors для масіваў, хэшаў і дыяпазонаў. Ды й увогуле паспрабайце для ўсіх класаў, пра якія Вы ведаеце!

Модулі

Паспрабуйце:

  • Array.ancestors
  • Array.superclass
  • Array.superclass.superclass
  • Array.superclass.superclass.superclass

ancestors кажа што ланцужок спадкаваньня Array ўключае Enumerable і Kernel, але калі мы падыходзім да канца ланцужка спадкаваньняў – BasicObject, мы ня бачым ніводнага з гэтых класаў. Што адбываецца?

Enumerable і Kernel насамрэч не зьяўляюцца класамі; яны ёсьць модулі (modules). Модулі – гэта набор мэтадаў і канстант, якія могуць быць даданы ў некалькі класаў. Модуль Kernel уключаны ў клас Object, і таму, кожны клас, які ўспадкоўваецца ад Object, мае функцыянальнасьць Kernel. Праглядзіце дакумэнтацыю Ruby для Kernel; Вы ўбачыце што Вы карысталіся штам якімі мэтадамі Kernel бяз усьведамленьня гэтага.

Каб зразумець Enumerable, паглядзіце на Hash.ancestors. Ён і тут таксама! Enumerable – гэта модуль, які можаць быць уключаны ў любы клас, які трымае якую-небудзь калекцыю рэчаў. Шмат мэтадаў, якія мы ведаем для масіваў будуць таксама працаваць і для хэшаў, таму што гэтыя мэтады насамрэч частка модуля Enumerable. Чэканіце дакумэнтацыю Ruby для Enumerable.

Класы гэта таксама аб’екты

Паглядзіце на гэта:

  • 5.class
  • Fixnum.class

Калі мы друкуем Fixnum.class, мы выклікаем мэтад у класа. Ці не выглядае гэта трошкі странна? Мы размаўлялі пра тое, што мэтады можна выклікаць толькі ў аб’ектаў?

Атрымліваецца што класы таксама аб’екты. Паспрабуйце:

  • 5.methods
  • Fixnum.methods

Трошкі тэрміналёгіі: 5 гэта аб’ект класа Fixnum. Гэтак жа "blah" – гэта аб’ект класа String.

Мэтад які выклікаецца ў класа завецца мэтадам класа. Мэтад які выклікаецца ў асобніка класа завецца мэтад асобніка.

Вельмі распаўсюджаны мэтад класаў – гэта new. Паспрабуйце яго для розных класаў. Што ён робіць?

Зараз мы ведаем тры тыпа мэтадаў: мэтады аб’ектаў (асобнікаў), якія робяць дзеяньні над аб’ектамі класаў; мэтады класаў, якія робяць дзеяньні над класамі; і глабальныя мэтады, якія ня робяць дзе над чымсьці канкрэтным. (Тэхнічна, глабальныя мэтады зьяўляюцца мэтадамі класа Object.)

У Ruby, амаль усе аб’ект. Спачатку гэта падаецца трошкі дзіўным, але Вы звыкніцеся :)

Стан і паводзіны

Адзін з спосабаў як думаць пра аб’ект, гэта стан і паводзіны: стан, маючы на ўвазе, што аб’ект няме нейкую інфармацыю пра сябе, і паводзіны, маючы на ўвазе, што Вы можаце выклікаць якія-небудзь мэтады ў аб’екта. Напрыклад, аб’ект 5.8 зьмяшчае інфармацыю, якая кажа Ваш, што ён прадстаўляе лік 5.8; таксама аб’ект 5.8 прымае выклікі мэтадаў як round і abs.

Такім чынам можна разглядаць клас як план (шаблён) будучага аб’екта, як вызначае якім аб’ект будзе.

Калі Вы спрабавалі рабіць нешта накшталт гэтага:

  • 5.even?
  • "hummingbird".even?

І атрымоўвалі памылку NoMethodError: undefined method even?' for "hummingbird":String, заразы Вы разумееце што яна значыць. Мы ня можам выклікаць even? у “hummingbird”, таму што няма мэтада even? у класа String.

Тое ж самае з:

  • "i am a string".reverse
  • 782349.reverse

Тым ня менш, аб’екты часта маюць аднолькавыя імёны:

  • "i am a string".length
  • ["i", "am", "an", "array"].length

Або мэтад можа быць у модуле, які ўключаны ў шмат класаў. Напрыклад мэтады модуля Enumerable.

Ёсьць спецыяльны мэтад каб паглядзець мэтады аб’екта – methods:

  • 3.methods

Вось як можна даведацца пра мэтады аб’екта, за выключэньнем мэтадаў класа: 3.methods - Object.new.methods. Падумайце што значыць гэтый код?

Наступны занятак