Ruby privát osztály módszerek

24 Jan 2016

a Ruby programozási nyelvben a definiált metódusok két változatban léteznek: példány metódusok és osztály metódusok. A példánymódszerek az objektum inicializálása után állnak rendelkezésre, létrehozva egy példányt. Osztály metódusok, másrészről, rendelkezésre állnak anélkül, hogy létrehoznák annak az osztálynak a példányát, amelyen meg vannak határozva.

a Ruby módszerek láthatósága változhat. A nyilvános metódusok bármilyen kontextusban elérhetők, míg a privát metódusok elérhetősége korlátozott az osztály és leszármazottai példányán belül. A harmadik láthatósági hatókör, védett, hasonlóan viselkedik, mint a magán metódusok, de a védett metódusokat ugyanazon osztály más példányai is meghívhatják.

a gyors frissítéshez a nyilvános és a privát példány metódusai így néznek ki:

class Dog def do_trick bark end private def bark puts 'woof woof' endend

amikor a nyilvános módszert hívják:

> dog = Dog.new> dog.do_trick# => woof woof

a privát módszer:

> dog = Dog.new> dog.bark# => NoMethodError: private method `bark' called for <Dog>

lehet, hogy a privát osztály metódusok nem olyan gyakoriak, mint a privát példány metódusok, de még mindig megvan a helyük. Például egy osztály metódushoz belső segítő metódusokra lehet szükség a funkció befejezéséhez. Bármi is legyen az oka, a magánosztály módszereinek meghatározása értékes, de nem mindig intuitív.

ez a példa Dog osztálynak fenn kell tartania a tricks listát, amelyet a többi nyilvános osztály metódusán belül használnak. Ez a lista nem lehet elérhető a Dog osztályon kívüli hívók számára.

a rossz út

az első lépés a privát tricks módszer írásakor úgy nézhet ki, mint:

class Dog private def self.tricks endend

a tricks módszer láthatóságának tesztelésekor azonban:

> Dog.tricks# => 

Uh oh, nem volt hiba, jelezve, hogy egy privát módszert hívtak, ez a módszer teljesen nyilvános.

miért?

annak oka, hogy a fenti kód nem hozott létre privát metódust, a Ruby objektumhierarchiájához, a belső osztályok közötti interakciókhoz, az osztályok példányaihoz és a sajátosztályokhoz kapcsolódik. Egy részletes írás arról, hogy Ruby tárgyai hogyan működnek egymással, megtalálható egy előző bejegyzésben.

egy osztály metódusainak meghatározásakor az alapértelmezett kontextus és a self. metódus deklaráció által bevezetett kontextus elkülönül egymástól.

a privát metódus hatóköre nem használható a fenti módon, mivel nem kezeli a Dog osztályban és a self kontextusban definiált módszerek közötti kontextusváltást.

tehát mi az alternatíva?

class << self

az objektum osztály metódusainak meghatározásának egyik alternatív módja a class << self szintaxis használata. Ez a szintaxis megnyit egy sajátosztályt a mellékelt argumentumhoz. Ebben a példában a self a Dog osztályon belül megnyitja a Dog's sajátosztályt.

class Dog class << self private def tricks end endend

egy dolgot meg kell jegyezni, hogy az ilyen módszerek meghatározásakor a deklaráció def self.tricks – ről egyszerűen def tricks – re változott.

most a magán hatókör megmarad, és a várható viselkedés megvalósul:

> Dog.tricks# => NoMethodError: private method `tricks' called for Dog:Class

modulok

a ruby modulok módszerek és állandók gyűjteményei. Ezek a gyűjtemények felhasználhatók kapszulázási eszközként, vagy ebben az esetben alternatívák a nyilvános és a privát osztály metódusainak meghatározására.

amikor egy osztály extends a modul, az összes metódusok belül modul lesz osztály módszerek a tárgy osztály*. Ez a minta használható a tricks módszer meghatározására Dog – en.

* Megjegyzés: Ez csak a “tipikus értelemben” definiált módszerekre vonatkozik bármely def self. vagy def Dog.metódusdefiníciók egy modulban nem válnak automatikusan osztály metódusokká ugyanúgy, amikor extended.

class Dog module ClassMethods private def tricks end end extend ClassMethodsend> Dog.tricks# => NoMethodError: private method `tricks' called for Dog:Class

ennek a megközelítésnek az előnye az olvashatóság. A ClassMethods nevű modul, amelyet a Dog osztály tartalmaz és így kapszuláz, az összes kívánt osztálymódszer tiszta otthona.

a láthatósági módosítók, mint például az private ennek megfelelően viselkednek, és a moduldefiníció alján található egyszerű extend összehozza az egészet.

private_class_method

a harmadik megközelítés a beépített módszer használata Module#private_class_method. Ennek a módszernek az a célja, hogy megváltoztassa a meglévő osztálymódszerek láthatóságát.

a másik két megoldástól eltérően ez nem igényel más módszermeghatározási stílust, mint a helytelen megoldás:

class Dog def self.tricks end private_class_method :tricksend> Dog.tricks# => NoMethodError: private method `tricks' called for Dog:Class

ez a módszer az osztály metódus-meghatározása során is beilleszthető:

class Dog private_class_method def self.tricks endend> Dog.tricks# => NoMethodError: private method `tricks' called for Dog:Class

ha egy osztály metódusnak privátnak kell lennie, és a sorok mentése nagyon fontos, akkor ez a stílus alkalmazható; de, minden bizonnyal feláldozza az olvashatóság szintjét.

a private_class_method fő erőssége az explicitsége. A többi megközelítéstől eltérően ez nem igényel speciális moduldefiníciót vagy módszerdefiníciós kontextusváltást.

további olvasmányok

a fent említett megoldások elvégzik a munkát, de nem biztos, hogy megválaszolják az elhúzódó kérdéseket arról, hogy miért működnek a dolgok úgy, ahogy. Néhány nagyszerű cikk a ruby eigenclass – ról és Matz gondolatairól a Ruby method design – ról segíthet egy tömörebb képet festeni arról, hogy miért összetett A Ruby private class method definíciója.

You might also like

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.