Ruby Private Klasse Metoder

24 Jan 2016

I Programmeringsspråket Ruby kommer definerte metoder i to varianter: instansmetoder og klassemetoder. Instansmetoder er tilgjengelige etter at et objekt er initialisert, og oppretter en forekomst. Klassemetoder, derimot, er tilgjengelige uten å opprette en forekomst av klassen de er definert på.

Ruby-metoder kan variere i synlighet. Offentlige metoder er tilgjengelige i enhver sammenheng, mens private metoder er begrenset i forekomsten av en klasse og dens etterkommere. Et tredje synlighetsområde, beskyttet, oppfører seg på samme måte som private metoder, men beskyttede metoder kan kalles av andre forekomster av samme klasse.

for en rask oppfriskning ser offentlige og private instansmetoder slik ut:

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

når den offentlige metoden kalles:

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

den private metoden:

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

Private klassemetoder er kanskje ikke like vanlige som private instansmetoder, men de har fortsatt sin plass. For eksempel kan en klassemetode kreve interne hjelpemetoder for å fullføre sin funksjon. Uansett årsak, definere private klasse metoder har verdi, men er ikke alltid intuitivt.

dette eksemplet Dog klassen må opprettholde en liste over tricks som skal brukes i de andre metodene for offentlig klasse. Denne listen skal ikke være tilgjengelig for innringere utenfor klassen Dog.

feil vei

et første pass ved å skrive privat tricks – metoden kan se ut:

class Dog private def self.tricks endend

Men når du tester synligheten til tricks – metoden:

> Dog.tricks# => 

Uh oh, ingen feil ble kastet som indikerer at en privat metode ble kalt, denne metoden er helt offentlig.

Hvorfor?

grunnen til at koden ovenfor ikke produserte en privat metode, har Å gjøre med Rubys objekthierarki, interaksjoner mellom interne klasser, forekomster av disse klassene og eigenclasses. En detaljert skrive opp om Hvordan Ruby objekter arbeide med hverandre kan bli funnet i et tidligere innlegg.

når du definerer metoder i en klasse, er standardkonteksten og konteksten introdusert av metodedeklarasjonen self. distinkte.

det private metodeområdet kan ikke brukes på ovennevnte måte, da det ikke håndterer kontekstendringen mellom metoder definert i Dog – klassen og definert i self – konteksten.

så hva er alternativene?

klasse < < selv

en alternativ måte å definere klassemetoder på et objekt er å bruke syntaksen class << self. Denne syntaksen åpner en egenklasse for det medfølgende argumentet. I dette eksemplet vil self i Dog – klassen åpne Dog's egenklassen.

class Dog class << self private def tricks end endend

En ting å merke seg er at når man definerer metoder som dette, har erklæringen endret seg fra def self.tricks til bare def tricks.

nå bevares det private omfanget og forventet oppførsel oppnås:

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

Moduler

Moduler I ruby er samlinger av metoder og konstanter. Disse samlingene kan brukes som innkapslingsverktøy eller i dette tilfellet alternativer til å definere offentlige og private klassemetoder.

når en klasse extends en modul, blir alle metodene i den modulen klassemetoder på emneklassen*. Dette mønsteret kan brukes til å definere tricks – metoden på Dog.

* Merknad: Dette gjelder bare metoder definert i en «typisk forstand» noen def self. eller def Dog. metodedefinisjoner i en modul blir ikke automatisk klassemetoder på samme måte når extended.

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

en fordel med denne tilnærmingen er lesbarhet. Modulen som heter ClassMethods, som er inneholdt og dermed innkapslet av Dog – klassen, er det klare hjemmet for alle ønskede klassemetoder.

Synlighetsmodifikatorer som private oppfører seg tilsvarende, og en enkel extend nederst i moduldefinisjonen bringer alt sammen.

private_class_method

en tredje tilnærming er å bruke den innebygde metoden Module#private_class_method. Formålet med denne metoden er å endre synligheten til eksisterende klassemetoder.

I Motsetning til de to andre løsningene, krever denne ikke en annen metode for definisjon fra feil løsning:

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

denne metoden kan også være in-lined under klassens metodedefinisjon:

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

Hvis en enkelt klassemetode må være privat og lagre linjer er svært viktig, kan denne stilen være aktuelt; men det ofrer absolutt et nivå av lesbarhet.

en stor styrke på private_class_method er dens eksplisitt. I motsetning til de andre tilnærmingene krever denne ikke en spesiell moduldefinisjon eller metodedefinisjons kontekstsvitsjing.

Videre Lesing

de nevnte løsningene vil få jobben gjort,men kan ikke svare på dvelende spørsmål om hvorfor ting fungerer som de gjør. Noen gode artikler om ruby eigenclass og Matz tanker Om Ruby metode design bør bidra til å male et mer konsist bilde av hvorfor Ruby private class metode definisjon er kompleks.

You might also like

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.