av Nishant Mishra
som datavetenskapsstudent spenderar jag mycket tid på att lära och leka med nya språk. Varje nytt språk har något unikt att erbjuda. Med detta sagt börjar de flesta nybörjare sin programmeringsresa med antingen procedurspråk som C eller med objektorienterade språk som JavaScript och C++.
därför är det vettigt att gå igenom grunderna i objektorienterad programmering så att du kan förstå begreppen och tillämpa dem på de språk du lär dig enkelt. Vi kommer att använda Ruby programmeringsspråk som ett exempel.
du kanske frågar, Varför Ruby? Eftersom det är” utformat för att göra programmerare lyckliga ” och också för att nästan allt i Ruby är ett objekt.
få en känsla av objektorienterat Paradigm (OOP)
i OOP identifierar vi de ”saker” som vårt program hanterar. Som människor tänker vi på saker som objekt med attribut och beteenden, och vi interagerar med saker baserat på dessa attribut och beteenden. En sak kan vara en bil, en bok och så vidare. Sådana saker blir klasser (ritningar av objekt), och vi skapar objekt ur dessa klasser.
varje instans (objekt) innehåller instansvariabler som är objektets tillstånd (attribut). Objektbeteenden representeras av metoder.
Låt oss ta exemplet med en bil. En bil är en sak som skulle göra det till en klass. En viss typ av bil, säger BMW är ett föremål för klassbilen. Attributen / egenskaperna hos en BMW som färg och modellnummer kan lagras i instansvariabler. Och om du vill utföra en operation av objektet, till exempel körning, beskriver ”drive” ett beteende som definieras som en metod.
en snabb Syntaxlektion
- för att avsluta en rad i ett Ruby-program, ett semikolon(;) är valfritt (men används vanligtvis inte)
- 2-mellanslag för varje kapslad nivå uppmuntras (krävs inte, som det är i Python)
- inga lockiga hängslen
{}
används och slutnyckelordet används för att markera slutet på ett flödeskontrollblock - för att kommentera använder vi
#
symbolen
hur objekt skapas i Ruby är genom att anropa en ny metod i en klass, som i exemplet nedan:
class Car def initialize(name, color) @name = name @color = color end
def get_info "Name: #{@name}, and Color: #{@color}" endend
my_car = Car.new("Fiat", "Red")puts my_car.get_info
för att förstå vad som händer i koden ovan:
- vi har en klass som heter
Car
med två metoder,initialize
ochget_info
. - instansvariabler i Ruby börjar med
@
(till exempel@name
). Det intressanta är att variablerna inte ursprungligen deklareras. De kommer till existens när de först används, och efter det är de tillgängliga för alla instansmetoder i klassen. - anropar metoden
new
gör att metodeninitialize
anropar.initialize
är en speciell metod som används som konstruktör.
åtkomst till Data
instansvariabler är privata och kan inte nås utanför klassen. För att komma åt dem måste vi skapa metoder. Instansmetoder har allmän åtkomst som standard. Vi kan begränsa åtkomsten till dessa instansmetoder som vi kommer att se senare i den här artikeln.
för att få och ändra data behöver vi ”getter” respektive ”setter” – metoder. Låt oss titta på dessa metoder med samma exempel på en bil.
class Car def initialize(name, color) # "Constructor" @name = name @color = color end
def color @color end
def color= (new_color) @color = new_color endend
my_car = Car.new("Fiat", "Red")puts my_car.color # Red
my_car.color = "White"puts my_car.color # White
i Ruby definieras” getter ”och” setter ” med samma namn som instansvariabeln som vi har att göra med.
i exemplet ovan, när vi säger my_car.color
, kallar det faktiskt color
– metoden som i sin tur returnerar färgens namn.
Obs: Var uppmärksam på hur Ruby tillåter ett mellanslag mellan color
och lika med att signera när du använder setter, även om metodnamnet är color=
genom att skriva dessa getter/setter-metoder kan vi ha mer kontroll. Men för det mesta är det enkelt att få det befintliga värdet och ställa in ett nytt värde. Så det borde finnas ett enklare sätt istället för att faktiskt definiera getter/setter-metoder.
det enklare sättet
genom att använda formuläret attr_*
istället kan vi få det befintliga värdet och ställa in ett nytt värde.
-
attr_accessor
: för getter och setter båda -
attr_reader
: endast för getter -
attr_writer
: för setter endast
Låt oss titta på detta formulär med samma exempel på en bil.
class Car attr_accessor :name, :colorend
car1 = Car.newputs car1.name # => nil
car1.name = "Suzuki"car1.color = "Gray"puts car1.color # => Gray
car1.name = "Fiat"puts car1.name # => Fiat
på så sätt kan vi hoppa över getter/setter-definitionerna helt och hållet.
prata om bästa praxis
i exemplet ovan initierade vi inte värdena för instansvariablerna @name
och @color
, vilket inte är en bra praxis. Eftersom instansvariablerna är inställda på noll, har objektet car1
ingen mening. Det är alltid en bra praxis att ställa in instansvariabler med en konstruktör som i exemplet nedan.
class Car attr_accessor :name, :color def initialize(name, color) @name = name @color = color endend
car1 = Car.new("Suzuki", "Gray")puts car1.color # => Gray
car1.name = "Fiat"puts car1.name # => Fiat
klassmetoder och Klassvariabler
så klassmetoder åberopas på en klass, inte på en instans av en klass. Dessa liknar statiska metoder i Java.
notera: self
utanför metoddefinitionen hänvisar till klassobjektet. Klassvariabler börjar med @@
nu finns det faktiskt tre sätt att definiera klassmetoder i Ruby:
inuti klassdefinitionen
- använda nyckelordet själv med namnet på metoden:
class MathFunctions def self.two_times(num) num * 2 endend
# No instance createdputs MathFunctions.two_times(10) # => 20
2. Använda <<
; själv
class MathFunctions class << self def two_times(num) num * 2 end endend
# No instance createdputs MathFunctions.two_times(10) # => 20
utanför klassdefinitionen
3. Använda klassnamn med metodnamnet
class MathFunctionsend
def MathFunctions.two_times(num) num * 2end
# No instance createdputs MathFunctions.two_times(10) # => 20
Klassarv
i Ruby ärver varje klass implicit från Objektklassen. Låt oss titta på ett exempel.
class Car def to_s "Car" end
def speed "Top speed 100" endend
class SuperCar < Car def speed # Override "Top speed 200" endend
car = Car.newfast_car = SuperCar.new
puts "#{car}1 #{car.speed}" # => Car1 Top speed 100puts "#{fast_car}2 #{fast_car.speed}" # => Car2 Top speed 200
i exemplet ovan åsidosätter klassen SuperCar
metoden speed
som ärvs från klassen Car
. Symbolen &
lt; betecknar arv.
Obs: Ruby stöder inte flera arv, och så används mix-ins istället. Vi kommer att diskutera dem senare i den här artikeln.
moduler i Ruby
en Ruby-modul är en viktig del av Ruby-programmeringsspråket. Det är en viktig objektorienterad funktion i språket och stöder flera arv indirekt.
en modul är en behållare för klasser, metoder, konstanter eller till och med andra moduler. Som en klass, en modul kan inte instansieras, men tjänar två huvudsakliga syften:
- namnrymd
- blanda in
moduler som namnrymd
många språk som Java har tanken på paketstrukturen, bara för att undvika kollision mellan två klasser. Låt oss titta på ett exempel för att förstå hur det fungerar.
module Patterns class Match attr_accessor :matched endend
module Sports class Match attr_accessor :score endend
match1 = Patterns::Match.newmatch1.matched = "true"
match2 = Sports::Match.newmatch2.score = 210
i exemplet ovan, eftersom vi har två klasser som heter Match
, kan vi skilja mellan dem och förhindra kollision genom att helt enkelt inkapsla dem i olika moduler.
moduler som Mix-in
i det objektorienterade paradigmet har vi begreppet gränssnitt. Mix – in ger ett sätt att dela kod mellan flera klasser. Inte bara det, vi kan också inkludera de inbyggda modulerna som Enumerable
och göra vår uppgift mycket enklare. Låt oss se ett exempel.
module PrintName attr_accessor :name def print_it puts "Name: #{@name}" endend
class Person include PrintNameend
class Organization include PrintNameend
person = Person.newperson.name = "Nishant"puts person.print_it # => Name: Nishant
organization = Organization.neworganization.name = "freeCodeCamp"puts organization.print_it # => Name: freeCodeCamp
Mix-ins är extremt kraftfulla, eftersom vi bara skriver koden en gång och sedan kan inkludera dem var som helst efter behov.
omfattning i Ruby
vi kommer att se hur omfattning fungerar för:
- variabler
- konstanter
- block
variablernas omfattning
metoder och klasser definierar ett nytt omfång för variabler, och yttre omfång variabler överförs inte till det inre omfånget. Låt oss se vad det betyder.
name = "Nishant"
class MyClass def my_fun name = "John" puts name # => John end
puts name # => Nishant
den yttre name
variabeln och den inre name
variabeln är inte desamma. Den yttre name
variabeln överförs inte till det inre omfånget. Det betyder att om du försöker skriva ut det i det inre omfånget utan att definiera det igen, skulle ett undantag kastas — ingen sådan variabel finns
omfattning av konstanter
ett inre omfång kan se konstanter definierade i det yttre omfånget och kan också åsidosätta de yttre konstanterna. Men det är viktigt att komma ihåg att även efter att ha åsidosatt det konstanta värdet i det inre omfånget förblir värdet i det yttre omfånget oförändrat. Låt oss se det i aktion.
module MyModule PI = 3.14 class MyClass def value_of_pi puts PI # => 3.14 PI = "3.144444" puts PI # => 3.144444 end end puts PI # => 3.14end
omfattning av block
Block ärver det yttre omfånget. Låt oss förstå det med ett fantastiskt exempel som jag hittade på internet.
class BankAccount attr_accessor :id, :amount def initialize(id, amount) @id = id @amount = amount endend
acct1 = BankAccount.new(213, 300)acct2 = BankAccount.new(22, 100)acct3 = BankAccount.new(222, 500)
accts =
total_sum = 0accts.each do |eachAcct| total_sum = total_sum + eachAcct.amountend
puts total_sum # => 900
i ovanstående exempel, om vi använder en metod för att beräkna total_sum
, skulle total_sum
variabeln vara en helt annan variabel inuti metoden. Det är därför ibland att använda block kan spara oss mycket tid.
med detta sagt är en variabel skapad inuti blocket endast tillgänglig för blocket.
åtkomstkontroll
när du utformar en klass är det viktigt att tänka på hur mycket av det du kommer att exponera för världen. Detta kallas inkapsling och betyder vanligtvis att dölja objektets interna representation.
det finns tre nivåer av åtkomstkontroll i Ruby:
- Offentlig – ingen åtkomstkontroll verkställs. Vem som helst kan kalla dessa metoder.
- skyddad – kan åberopas av objekt av de definierande klasserna eller dess underklasser.
- Privat – kan inte åberopas förutom med en explicit mottagare.
Låt oss se ett exempel på inkapsling i aktion:
class Car def initialize(speed, fuel_eco) @rating = speed * comfort end
def rating @rating endend
puts Car.new(100, 5).rating # => 500
nu, eftersom detaljerna om hur betyget beräknas hålls inne i klassen, kan vi ändra det när som helst utan någon annan förändring. Vi kan inte heller ställa in betyg från utsidan.
prata om sätten att ange åtkomstkontroll, det finns två av dem:
- ange offentliga, skyddade eller privata och allt tills nästa nyckelordskontroll kommer att ha den åtkomstkontrollnivån.
- definiera metoden regelbundet och ange sedan offentliga, privata och skyddade åtkomstnivåer och lista kommatecken(,) separerade metoder under dessa nivåer med metodsymboler.
exempel på det första sättet:
class MyClass private def func1 "private" end protected def func2 "protected" end public def func3 "Public" endend
exempel på det andra sättet:
class MyClass def func1 "private" end def func2 "protected" end def func3 "Public" end private :func1 protected :func2 public :func3end
de offentliga och privata åtkomstkontrollerna används mest.
slutsats
dessa är själva grunderna för objektorienterad programmering i Ruby. Nu, genom att känna till dessa begrepp kan du gå djupare och lära dig dem genom att bygga coola saker.
glöm inte att klappa och följa om du gillade! Håll dig uppdaterad här.