Ruby Private Class-menetelmät

24 tammi 2016

Ruby-ohjelmointikielessä määriteltyjä menetelmiä on kaksi varianttia: instanssimenetelmät ja luokkamenetelmät. Instanssimenetelmät ovat käytettävissä olion alustamisen jälkeen, jolloin luodaan instanssi. Luokkamenetelmät taas ovat käytettävissä luomatta esiintymää siitä luokasta, johon ne on määritelty.

Ruby-menetelmien näkyvyys voi vaihdella. Julkiset menetelmät ovat käytettävissä kaikissa yhteyksissä, kun taas yksityisten menetelmien saatavuus on rajoitettu luokan ja sen jälkeläisten tapauksessa. Kolmas näkyvyysalue, suojattu, käyttäytyy samalla tavalla kuin yksityiset menetelmät, mutta suojattuja menetelmiä voidaan kutsua myös muilla saman luokan instansseilla.

nopeassa kertauksessa julkisen ja yksityisen instanssin menetelmät näyttävät tältä:

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

kun julkista menetelmää kutsutaan:

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

ja yksityinen menetelmä:

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

Private class-menetelmät eivät välttämättä ole yhtä yleisiä kuin private instance-menetelmät, mutta niillä on silti paikkansa. Esimerkiksi luokkamenetelmä voi vaatia sisäisiä auttajamenetelmiä suorittaakseen tehtävänsä. Oli syy mikä tahansa, private class-menetelmien määrittelyllä on arvoa, mutta se ei ole aina intuitiivista.

tässä esimerkissä Dog luokka on pidettävä yllä luetteloa tricks, jota käytetään muissa julkisen luokan menetelmissä. Tämä luettelo ei saisi olla Dog – luokan ulkopuolisten soittajien saatavilla.

väärä tie

ensisyöttö kirjoittaessa yksityinen tricks menetelmä voi näyttää:

class Dog private def self.tricks endend

kuitenkin testattaessa tricks – menetelmän näkyvyyttä:

> Dog.tricks# => 

Oho, ei virhe heitettiin osoittaa, että yksityinen menetelmä oli nimeltään, tämä menetelmä on täysin julkinen.

miksi?

syy siihen, ettei yllä oleva koodi tuottanut yksityistä menetelmää, liittyy Rubyn objektihierarkiaan, sisäisten luokkien väliseen vuorovaikutukseen, näiden luokkien esiintymiin ja eigenclasseihin. Yksityiskohtainen kirjoitus siitä, miten Rubyn esineet toimivat keskenään, löytyy aiemmasta viestistä.

luokittain määriteltäessä on erotettava oletuskonteksti ja self. menetelmäilmoituksessa esitetty konteksti.

yksityisen menetelmän soveltamisalaa ei voida käyttää edellä mainitulla tavalla, koska se ei käsittele Dog luokassa määriteltyjen ja self kontekstissa määriteltyjen menetelmien välistä asiayhteyden muutosta.

joten mitkä ovat vaihtoehdot?

Luokka << self

yksi vaihtoehtoinen tapa määritellä luokkamenetelmiä objektille on käyttää class << self syntaksia. Tämä syntaksi avaa eigenclass toimitetulle argumentille. Tässä esimerkissä self Dog luokan sisällä avaa Dog's eigenclass.

class Dog class << self private def tricks end endend

on huomattava, että tämänkaltaisia menetelmiä määriteltäessä julistus on muuttunut def self.tricks: stä yksinkertaisesti def tricks: ksi.

nyt yksityinen laajuus säilyy ja odotettu käyttäytyminen saavutetaan:

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

moduulit

moduulit Rubyssa ovat menetelmien ja vakioiden kokoelmia. Näitä kokoelmia voidaan käyttää kapselointivälineinä tai tässä tapauksessa vaihtoehtoina julkisen ja yksityisen luokan menetelmien määrittelylle.

kun Luokka extends a moduuli, kaikki kyseisen moduulin menetelmät muuttuvat luokkamenetelmiksi aiheluokassa*. Tätä kaavaa voidaan käyttää tricks – menetelmän määrittelyyn Dog.

* Huom.: Tämä koskee vain ”tyypillisessä merkityksessä” määriteltyjä menetelmiä, jotka eivät ole def self. tai def Dog. moduulin metodimääritelmät eivät automaattisesti muutu luokan menetelmiksi samalla tavalla, kun extended.

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

tämän lähestymistavan etuna on luettavuus. ClassMethods – niminen moduuli, joka sisältyy ja siten kapseloi Dog – luokan, on selkeä koti kaikille halutuille luokkamenetelmille.

näkyvyyden modifioijat kuten private käyttäytyvät sen mukaisesti ja yksinkertainen extend modulin määritelmän alareunassa tuo kaiken yhteen.

private_class_method

kolmas lähestymistapa on käyttää rakennettua menetelmää Module#private_class_method. Menetelmän tarkoituksena on muuttaa olemassa olevien luokkamenetelmien näkyvyyttä.

toisin kuin kaksi muuta ratkaisua, tämä ei vaadi erityylistä menetelmän määrittelyä virheellisestä ratkaisusta:

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

tämä menetelmä voidaan myös vuorata luokan ’ menetelmän määrittelyn aikana:

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

jos yhden luokan menetelmä on yksityinen ja säästö linjat on erittäin tärkeää, tämä tyyli voi olla sovellettavissa; mutta, se varmasti uhraa tason luettavuus.

private_class_method suuri vahvuus on sen eksplisiittisyys. Toisin kuin muut lähestymistavat, tämä ei vaadi erityistä moduulin määrittelyä tai menetelmän määrittelyä konteksti kytkentä.

Jatkoluku

edellä mainitut ratkaisut hoitavat homman, mutta eivät välttämättä vastaa viipyileviin kysymyksiin siitä, miksi asiat toimivat niin kuin toimivat. Muutama suuri artikkeleita ruby eigenclass ja Matz ajatuksia Ruby method design pitäisi auttaa maalata tiiviimpi kuva, miksi Ruby ’ s private class method määritelmä on monimutkainen.

You might also like

Vastaa

Sähköpostiosoitettasi ei julkaista.