Ruby for Newbies Operatörer och deras metoder

Ruby är ett av de mest populära språk som används på webben. Vi har startat en ny screencast-serie här på Nettuts + som kommer att introducera dig till Ruby, liksom de stora ramar och verktyg som följer med Ruby-utvecklingen. I den här lektionen tar vi en djupare titt på operatörer i Ruby, och varför de skiljer sig från vad du någonsin sett tidigare.


operatörer

Du har bekant med operatörer.

1 + 2 # 3 person [: name] = "Joe"

Operatörer är saker som plustecknet (en av de aritmetiska operatörerna) eller likhetsskylten (uppdragsoperatören). Dessa saker ser inte mycket annorlunda ut än de du använder i JavaScript, PHP eller något annat språk. Men som det mesta av Ruby-det finns mycket mer än vad ögat pågår här.

Här är hemligheten: Operatörer i Ruby är verkligen metodsamtal. Prova detta:

1. + (2) # 3

Här ringer vi på + operatör på objektet 1, passerar i objektet 2 som en parameter. Vi kommer tillbaka objektet 3. Vi kan också göra detta med strängar:

name = "Joe" namn. + ("Smith") # "Joe Smith", men "namn" är fortfarande "Joe" namn + = "Smith" # namn är nu "Joe Smith"

Som ni kan se kan vi göra strängförbindelser med + metod. Som en bonus här definierar ruby ​​+ = operatören baserat på + operatören (notera: du kan inte använda + = som metod).

Som du kanske inser, ger detta oss otroligt makt. Vi kan anpassa betydelsen av att lägga till, subtrahera och tilldela objekt i våra anpassade klasser. Vi såg hur det här fungerar med egenskaper på objekt i vår lektion på klasser (vi definierade en fast egendom och egendom = metod i klassen och fick det förväntade syntakssockret för att använda dem). Det vi tittar på här tar det ett steg längre.


Bygga våra egna operatörsmetoder

Låt oss försöka skapa en av dessa metoder själva. För det här exemplet, låt oss skapa ett kylskåpsobjekt, som vi kan lägga till saker till via + operatör och ta saker ut av via - operatör.

Här är början på vår klass:

klass kylskåp def initialisera (drycker = [], mat = []) @beverages = drycker @foods = livsmedel slut def + (objekt) slut def

Vår initialisera funktionen är ganska enkel: vi tar två parametrar (som faller tillbaka till tomma arrays om inget ges), och tilldelar dem till exempel variabler. Låt oss nu bygga de två funktionerna:

def + (post) om item.is_a? Dryck @ beverages.push objektet annat @ foods.push objektets slutända

Det här är ganska enkelt. Varje objekt har en är en? metod som tar en enda parameter: en klass. Om objektet är en förekomst av den klassen kommer den att återvända sant; annars kommer det att returnera falskt. Så säger detta att om objektet vi lägger till i kylskåpet är a Dryck, vi lägger till den i @drycker array. Annars lägger vi till den i @mat array.

Det är bra; nu, vad sägs om att ta saker ur kylskåpet? (Obs! Den här metoden skiljer sig från den som visas i videon, det här visar att dessa operatörsmetoder ger oss stor flexibilitet, de är egentligen bara normala metoder som du kan göra någonting med. Dessutom tycker jag att det här är en bättre version av metoden, men det är mer komplext.)

def - (item) ret = @ beverages.find do | dryck | beverage.name.downcase == item.downcase End Return @ beverages.delete rätt såvida inte ret.nil? ret = @ foods.find do | food | food.name.downcase == item.downcase slutet @ foods.delete ret end

Det här är vad som händer när vi använder minusoperatören. Parametern som det tar är en sträng, med namnet på objektet vi letar efter (Förresten skapar vi Dryck och Mat klasser snart). Vi börjar med att använda hitta metod som arrays har. Det finns några sätt att använda denna metod. vi passerar det ett block det här blocket säger att vi försöker hitta objektet i arrayen som har en namn egenskap som är densamma som strängen vi passerade in; notera att vi konverterar båda strängarna till små bokstäver, för att vara säkra.

Om det finns ett objekt som matchar i matrisen, lagras det i ret; annat, ret kommer vara noll. Därefter returnerar vi resultatet av @ beverage.delete rätt, som tar bort objektet från matrisen och returnerar det. Lägg märke till att vi använder en uttalande modifier i slutet av den raden: vi gör det här såvida inte ret är noll.

Du kanske undrar varför vi använder sökordet lämna tillbaka här, eftersom det inte krävs i Ruby. Om vi ​​inte använde den här, skulle funktionen inte återvända, eftersom det finns mer kod till funktionen. Använder sig av lämna tillbaka här tillåter oss att returnera ett värde från en plats som funktionen normalt inte skulle returnera.

Om vi ​​inte återvänder betyder det att objektet inte hittades i @drycker. Därför antar vi att det är i @foods. Vi gör samma sak för att hitta objektet i @foods och returnera sedan det.

Innan vi testar det här behöver vi vår Mat och Drycker klasser:

klass Beverage attr_accessor: namn def initiera namn @name = namn @time = Time.now slutet slutklass Mat attr_accessor: namn def initiera namn @name = namn @time = Time.now slutet slutet

Observera att jag inte gjorde i videon @namn tillgänglig från utsidan av objektet. Här gör jag det med attr_accessor: namn, så att vi kan kontrollera namnet på dessa objekt när de är inne i ett kylskåp.

Så, låt oss testa det i irb; vi börjar med att kräva den fil som innehåller koden; Ge sedan klasserna ett försök. Observera att jag har lagt till radbrytningar i utmatningen för enklare läsning.

> kräver "./lesson_6 '=> true> f = Kylskåp.new => # > f + Beverage.new ("vatten") => [#]> f + Food.new ("bröd") => [#]> f + Food.new ("eggs") => [#, # ]> f + Beverage.new ("apelsinjuice") => [#, # ]> f => #, # ], mat [#, # ]> f - "bröd" => # > f => #, #], mat [#]

När vi går längs kan du se att saker läggs till @drycker och @foods arrays, och sedan borttagna.


Få och sätt operatörer

Låt oss nu skriva metoder för de get och set operatörer som används med hash. Du har sett det här förut:

person =  person [: name] = "Joe"

Men eftersom dessa operatörer är metoder kan vi göra det på så vis:

person. [] = (: ålder, 35) # för att ställa person. [] (: namn) # för att få

Det är rätt; Det här är normala metoder, med speciellt socker för din användning.

Låt oss försöka vi ska göra en Klubb klass. Vår klubb med har medlemmar med olika roller. Vi kanske dock vill ha mer än en medlem med en viss roll. Så, vår Klubb Exempel kommer att hålla reda på medlemmarna och deras roller med en hash. Om vi ​​försöker att tilldela en andra medlem en roll, istället för att skriva över den första, lägger vi till den.

klass Club def initiera @members =  end def [] (roll) @members [roll] end def [] = (roll, medlem) änden

Fåversionen är ganska enkel; Vi vidarebefordrar det till @members array. Men set är lite mer komplicerat:

def [] == (roll, medlem) om @members [roll] .nil? @medlemmar [roll] = medlem elsif @members [roll] .is_a? String @members [roll] = [@members [roll], medlem] annat @members [roll] .push member end end

Om den här rollen inte har ställts in ställer vi bara in värdet på den nyckeln till vår medlems hash. Om den har ställts in som en sträng vill vi konvertera den till en matris, och sätta originalmedlemmen och den nya medlemmen i den matrisen. Slutligen, om ingen av dessa alternativ är sanna, är det redan en matris, och så trycker vi bara in medlemmen i matrisen. Vi kan testa den här klassen på följande sätt:

c = Club.new c [: chair] = "Joe" c [: ingenjör] = "John" c [: ingenjör] = "Sue" c [: stol] # "Joe" c [: engingeer] # ["John "," Sue "]

Varsågod!


Andra operatörer

Det här är inte de enda operatörerna som vi självklart kan göra. Här är hela listan:

  • Aritmetiska operatörer: + - * \
  • Få och sätt operatörer: [] [] =
  • Skovloperatör: <<
  • Jämförelseoperatörer: == < > <= >=
  • Case jämställdhetsoperatör: ===
  • Bitvis Operatör: | & ^

Tack för att du läser!

Om du har några frågor om den här lektionen, eller något annat som vi har diskuterat i Ruby, fråga i kommentarerna!