Luokka - olio-ohjelmoinnin malli , jolla luodaan tietyn tyyppisiä objekteja , kuvataan niiden rakenne (joukko kenttiä ja niiden alkutila) ja määritellään algoritmit (funktiot tai menetelmät ) näiden objektien kanssa työskentelemiseen.
Toisin sanoen luokka toimii välineenä abstraktien tietotyyppien tuomiseksi ohjelmistoprojektiin. Muille abstraktien tietotyyppien kuvaajille - metaluokille , rajapinnoille , rakenteille , enumeraatioille - on ominaista omat ominaisuutensa. Luokkien välisen eron ydin on, että tietotyyppiä määriteltäessä luokka määrittelee samanaikaisesti sekä rajapinnan että toteutuksen kaikille esiintymilleen (eli objekteille), joten konstruktorimetodin kutsuminen on pakollista.
Luokka on yksi OOP:n avainkäsitteistä , mutta on olemassa myös luokkattomia oliokieliä, kuten Self , JavaScript , Lua , (lisätietoja on kohdassa Prototyyppiohjelmointi ).
Käytännössä olio-ohjelmointi tarkoittaa useiden luokkien luomista, mukaan lukien käyttöliittymä ja toteutus, ja niiden käyttöä. Useiden luokkien ja niiden välisten suhteiden graafista esitystä kutsutaan luokkakaavioksi . Oliolähtöiseen lähestymistapaan on kehittämisen aikana kertynyt paljon suosituksia ( malleja ) luokkien ja luokkahierarkioiden luomiseen .
Idea luokista tuli tekoälytutkimukseen liittyvästä tietopohjatyöstä . Ihmisten käyttämät luokitukset eläintieteessä, kasvitieteessä, kemiassa, koneenosissa kantavat perusajatuksen, että mikä tahansa asia voidaan aina esittää jonkin yleisemmän käsitteen erikoistapauksena. Tietty omena on omena yleensä, omena yleensä ja mikä tahansa omena yleensä on hedelmä. (Omenat ja päärynät ovat yleinen esimerkki luokista olio-ohjelmoinnin opetusohjelmissa.)
Kaikkialla alla sanoja "luokka", " objekti ", " rajapinta " ja " rakenne " käytetään niiden erityismerkityksissä, jotka on annettu OOP:ssa.
Olio-ohjelmassa, joka käyttää luokkia, jokainen objekti on jonkin tietyn luokan " esiintymä ", eikä muita objekteja tarjota. Toisin sanoen " luokan esiintymä " ei tässä tapauksessa tarkoita "esimerkkiä jostakin luokasta" tai "yksittäistä luokkaa", vaan "objektia, jonka tyyppi on jokin luokka". Samanaikaisesti eri ohjelmointikielissä joidenkin muiden tietotyyppien olemassaolo on sallittua tai kiellettyä, joiden esiintymät eivät ole objekteja (eli kieli määrittää, ovatko esimerkiksi numerot, taulukot ja osoittimet objekteja tai ei, ja vastaavasti onko olemassa luokkia, kuten "numero", "taulukko" tai "osoitin", joista jokainen tietty numero, taulukko tai osoitin olisi esiintymä).
Esimerkiksi abstrakti tietotyyppi "tekstirivi" voidaan suunnitella luokaksi, jolloin kaikki ohjelman tekstirivit ovat objekteja - luokan "tekstirivi" esiintymiä.
Luokkia käytettäessä kaikki ohjelmakoodin elementit, kuten muuttujat, vakiot, menetelmät, menettelyt ja funktiot, voivat kuulua (ja monilla kielillä täytyy kuulua) johonkin luokkaan. Itse luokka määritellään viime kädessä luettelona sen jäsenistä , nimittäin kentistä ( ominaisuuksista ) ja menetelmistä/funktioista/prosedureista . Ohjelmointikielestä riippuen tähän luetteloon voidaan lisätä vakioita, attribuutteja ja ulkoisia määritelmiä.
Kuten rakenteet, luokat voivat määrittää kenttiä eli muuttujia, jotka kuuluvat joko suoraan itse luokkaan (staattinen) tai luokan esiintymiin (tavallinen). Staattiset kentät ovat olemassa yhdessä esiintymässä koko ohjelmalle (tai monimutkaisemmassa versiossa yhdessä ilmentymässä prosessia tai säiettä/säiettä kohti ). Tavallisia kenttiä luodaan yksi kopio kullekin tietylle objektille - luokan esiintymälle. Esimerkiksi ohjelman toiminnan aikana luotujen tekstirivien kokonaismäärä on "tekstirivi"-luokan staattinen kenttä. Ja tietty merkkijonon merkkijono on "tekstijono"-luokan esiintymän säännöllinen kenttä, aivan kuten "tekstijono"-tyypin muuttuja "sukunimi" on kunkin tietyn esiintymän säännöllinen kenttä. "henkilö"-luokasta.
OOP:ssa luokkia käytettäessä kaikki suoritettava ohjelmakoodi (algoritmit) esitetään ns. "metodeina", "funktioina" tai "menettelyinä", mikä vastaa perinteistä strukturoitua ohjelmointia , mutta nyt ne voivat (ja monien kielten täytyy kuulua johonkin tai toiseen luokkaan. Esimerkiksi, jos mahdollista, luokka "tekstijono" sisältää kaikki perusmenetelmät/toiminnot/menettelyt, jotka on suunniteltu toimimaan tekstijonon kanssa, kuten haku merkkijonosta, merkkijonon osan leikkaaminen jne.
Kuten kentät, luokkaan kuuluvien menetelmien/funktioiden/proseduurien muodossa oleva koodi voidaan viitata joko itse luokkaan tai luokan esiintymiin. Luokkaan kuuluva ja luokkaan liittyvä menetelmä (staattinen menetelmä) voidaan kutsua itsestään ja sillä on pääsy luokan staattisiin muuttujiin. Luokkainstanssiin liittyvää menetelmää (tavallinen menetelmä) voidaan kutsua vain itse objektilta, ja sillä on pääsy sekä luokan staattisiin kenttiin että tietyn objektin säännöllisiin kenttiin (kutsuttaessa tämä objekti välitetään piilotettu menetelmäparametri). Esimerkiksi luotujen merkkijonojen kokonaismäärä löytyy mistä tahansa ohjelmasta, mutta tietyn merkkijonon pituus selviää vain määrittämällä tavalla tai toisella, minkä merkkijonon pituutta mitataan.
Ohjelmoinnissa on käsite ohjelmointirajapinta, joka tarkoittaa luetteloa mahdollisista laskutoimituksista, jotka ohjelman yksi tai toinen osa voi suorittaa. Tämä sisältää kuvauksen: mitkä argumentit ja missä järjestyksessä on välitettävä luettelosta algoritmien syötteeseen, sekä mitä ja missä muodossa ne palautetaan. Abstrakti tietotyyppirajapinta keksittiin tällaisen listan formalisoitua kuvausta varten. Itse algoritmeja, eli varsinaista ohjelmakoodia, joka suorittaa kaikki nämä laskelmat, ei ole määritetty käyttöliittymässä, ne ohjelmoidaan erikseen ja niitä kutsutaan käyttöliittymän toteutukseksi .
Ohjelmointirajapintoja, kuten myös luokkia, voidaan laajentaa perinnön kautta , joka on yksi tärkeimmistä koodin uudelleenkäytön tavoista OOP:ssa. Peritty luokka tai käyttöliittymä sisältää kaiken, mikä on määritetty kaikille sen pääluokille (ohjelmointikielestä ja alustasta riippuen, se voi olla nollasta äärettömään). Voit esimerkiksi luoda oman version tekstimerkkijonosta perimällä "oma tekstijono" -luokan jo olemassa olevasta "tekstimerkkijono" -luokasta, vaikka oletetaan, että ohjelmoijan ei tarvitse kirjoittaa uudelleen hakualgoritmeja ja niin edelleen. koska ne peritään automaattisesti valmiista luokasta, ja mikä tahansa "tekstirivini" -luokan esiintymä voidaan välittää paitsi pääluokan "tekstirivi" valmiille menetelmille tarvittavien laskelmien suorittamiseksi, vaan myös yleinen kaikille algoritmeille, jotka voivat toimia "tekstirivi"-tyyppisten objektien kanssa, koska molempien luokkien esiintymät ovat yhteensopivia.
Luokan avulla voit asettaa ohjelmointirajapinnan lisäksi itseensä ja sen ilmentymiin, mutta myös kirjoittaa eksplisiittisesti laskelmista vastaavan koodin. Jos perimme käyttöliittymän uutta tietotyyppiä luodessaan, voimme välittää tietotyyppimme esiintymän mille tahansa algoritmille, joka voi toimia tämän rajapinnan kanssa. Meidän on kuitenkin kirjoitettava itse käyttöliittymän toteutus, eli ne algoritmit, joilla meitä kiinnostava algoritmi suorittaa laskelmia instanssimme avulla. Samanaikaisesti perimällä luokan perimme automaattisesti käyttöliittymän valmiin koodin (tämä ei aina pidä paikkaansa, emoluokka saattaa vaatia joidenkin algoritmien toteuttamista lapsiluokassa ilman epäonnistumista). Tämä koodista periytymiskyky tekee selväksi, että olio-ohjelmassa luokan tietotyyppi määrittelee sekä rajapinnan että toteutuksen kaikille esiintymilleen.
Yksi strukturoidun ohjelmoinnin ongelmista, jonka kanssa OOP kamppailee, on ohjelman muuttujien oikean arvon säilyttäminen. Usein eri ohjelmamuuttujat tallentavat loogisesti toisiinsa liittyviä arvoja, ja ohjelmoija on vastuussa tämän loogisen yhteyden ylläpitämisestä, eli yhteyttä ei ylläpidetä automaattisesti. Esimerkkinä ovat liput "potkut" ja "odottaa bonusta vuoden lopussa", kun henkilöstöosaston sääntöjen mukaan henkilöä voidaan samanaikaisesti jättää potkutta ja odottaa bonusta, olla potkutta ja odottaa bonus, potkut ja ei odota bonusta, mutta sitä ei voida sekä potkaista että odottaa bonusta. Toisin sanoen minkä tahansa ohjelman osan, joka valitsee "potku" -ruudun, tulee aina poistaa valinta "odottaa vuoden lopun bonuksia" -ruutua.
Hyvä tapa ratkaista tämä ongelma on tehdä "käynnistetty" lippu muuttumattomaksi kaikissa ohjelman osissa, paitsi yhdessä erikseen määritellyssä. Tässä nimenomaisessa osiossa kaikki kirjoitetaan kerran ja oikein, ja kaikkien muiden on viitattava tähän osaan aina, kun he haluavat valita "käynnistetty"-ruudun tai poistaa sen valinnan.
Olio-ohjelmassa "käynnistetty" lippu julistetaan jonkin luokan yksityiseksi jäseneksi ja kirjoitetaan vastaavat julkiset menetelmät sen lukemiseksi ja muuttamiseksi. Sääntöjä, jotka määrittävät mahdollisuuden tai mahdottomuuden muuttaa suoraan mitä tahansa muuttujaa, kutsutaan pääsyn laajuuksien asettamissäännöiksi. Sanat "yksityinen" ja "julkinen" ovat tässä tapauksessa niin kutsuttuja " pääsyn muokkaajia ". Niitä kutsutaan muokkaajiksi , koska joissakin kielissä niitä käytetään muuttamaan aiemmin asetettuja käyttöoikeuksia, kun luokka on peritty. Yhdessä luokat ja käyttöoikeusmuuntimet määrittävät pääsyalueen, eli jokaisella koodin osalla, riippuen siitä, mihin luokkaan se kuuluu, on oma pääsyalue suhteessa luokkansa tiettyihin elementteihin (jäseniin) ja muihin luokkiin, mukaan lukien muuttujat. , metodit, funktiot , vakiot jne. On olemassa perussääntö: mikään yhdessä luokassa ei näe toisen luokan yksityisiä jäseniä. Muihin, monimutkaisempiin sääntöihin verrattuna, eri kielillä on erilaiset pääsyn muokkaajat ja säännöt, joilla ne ovat vuorovaikutuksessa luokkien kanssa.
Melkein jokaiselle luokan jäsenelle voidaan asettaa pääsymuuttaja (poikkeuksena staattiset konstruktorit ja muutama muu seikka). Useimmat oliopohjaiset ohjelmointikielet tukevat seuraavia pääsyn muokkaajia:
Muuttujien oikean tilan ylläpitämisen ongelma on myös olennainen alkuarvojen asettamisen ensimmäisellä hetkellä. Tätä varten luokat tarjoavat erityisiä menetelmiä/funktioita, joita kutsutaan konstruktoreiksi. Mitään objektia (luokan ilmentymää) ei voi luoda muuten kuin kutsumalla suorittamaan konstruktorin koodi, joka palauttaa kutsujalle luodun ja oikein täytettynä luokan esiintymän. Monissa ohjelmointikielissä "struct"-tietotyyppi, kuten luokka, voi sisältää muuttujia ja menetelmiä, mutta rakenteiden esiintymiä, jotka jäävät vain merkityksi RAM-alueeksi, voidaan luoda ohittamalla rakentajat, mikä on kiellettyä luokkaesiintymissä ( lukuun ottamatta erityisiä poikkeuksellisia menetelmiä kaikkien vastaavien OOP-sääntöjen ohittamiseksi joillakin kielillä ja alustoilla). Tämä osoittaa eron luokkien ja muiden tietotyyppien välillä - rakentajakutsu tarvitaan.
Nykyaikaisissa olio-ohjelmointikielissä (mukaan lukien php , Java , C++ , Oberon , Python , Ruby , Smalltalk , Object Pascal ) luokan luominen edellyttää jonkin rakenteen kirjoittamista, joka sisältää joukon kenttiä ja menetelmiä (jälkimmäisten joukossa rakentajia erityinen rooli, tuhoajat, viimeistelijat). Käytännössä luokka voidaan ymmärtää mallina, jonka mukaan objektit luodaan - tämän luokan esiintymiä. Kaikki saman luokan esiintymät luodaan saman mallin mukaan, joten niillä on samat kentät ja menetelmät.
Luokan jäsenten laajuus (eli koodin laajuus, josta niihin pääsee määrittelemättömällä nimellä - ilman luokan tai objektin nimeä) ei riipu niiden laajuudesta ja on aina sama kuin luokan koodi. luokan menetelmiä.
Itse luokan laajuus on määritelty eri tavalla eri ohjelmointikielissä. Joissakin kielissä (kuten Delphi ) kaikilla luokilla on globaali näkyvyys (ottamalla huomioon moduulin näkyvyys ), toisissa (kuten Java ) luokan laajuus liittyy sen sisältävään käännösyksikköön (Javalla - paketilla ), muissa (kuten C ++ ja C# ) luokan laajuus määräytyy nimiavaruuksien ( nimiavaruuksien ) avulla, jotka ohjelmoija on nimenomaisesti asettanut ja jotka voivat vastata käännösyksiköitä tai olla keskenään ristiriidassa.
Delphissä luokka kuvataan seuraavasti:
TMyClass = class ( TObject ) yksityinen {Tässä osiossa kuvatut elementit eivät ole käytettävissä ulkopuolelta (luokan ulkopuolelta, mutta saatavilla moduulin sisällä).} {Luokkien kentät löytyvät yleensä täältä.} Tiukka yksityinen {Delphi 2007 ja uudemmat. Tässä osiossa kuvatut elementit ovat saatavilla vain luokassa} suojattu {Tässä osiossa kuvatut elementit ovat vain luokan ja kaikkien sen jälkeläisten käytettävissä.} julkinen {Tässä osiossa kuvatut elementit ovat kaikkien saatavilla.} julkaistu {Tässä kuvatut elementit -osio ovat kaikkien saatavilla ja näkyvät Object Inspector'e.} end ;Luokan esiintymä (objekti) luodaan seuraavasti:
MyClass := TMyClass . luoda ;Tuhottu näin:
FreeAndNil ( MyClass ) ; TAI MyClass . Ilmainen ;Luokka C++ :ssa luodaan seuraavasti:
class MyClass : public ParentClass // ParentClass - esi-isäluokka, jos sellainen on { julkinen : // tämän osan elementit ovat käytettävissä mistä tahansa ohjelman osasta MyClass (); // rakentaja ~ MyClass (); // tuhoaja suojattu : // Tämän osion elementit ovat käytettävissä luokasta ja sen jälkeläisistä yksityisistä : // tämän osion elementit ovat käytettävissä vain luokasta; tämä on oletusalue };Kun luokka on luotu, sitä pidetään täysimittaisena tietotyyppinä , ja siksi luokan esiintymät luodaan seuraavasti:
MyClass myinstance ;Soittaminen luokan jäsenille:
minun esimerkkini . luokan jäsenLuokan esiintymä tuhoutuu, kuten mikä tahansa muuttuja, vain, jos funktio , jossa se luotiin, on suorittanut työnsä tai jos luokalle varattu dynaaminen muisti on vapautettu väkisin .
C#:n luokat määritellään seuraavasti:
public class MyClass { //Jäsen saatavilla mille tahansa ohjelman luokalle public int k ; //Jäsen saatavilla mille tahansa luokalle samassa ohjelmamoduulissa sisäinen int l ; //Jäsen saatavilla mille tahansa luokalle samassa ohjelmamoduulissa tai vain nykyiselle luokalle ja kaikkiin sen alaluokkiin toisessa moduulissa suojattu sisäinen int m ; //Ainoastaan nykyiselle luokalle ja sen kaikille suojatuille alaluokille pääsevä jäsen int n ; //Jäsen käytettävissä vain nykyisestä luokasta (oletus). yksityinen int fg ; }Toisin kuin C++, pääsyn muokkaajat on määritettävä jäsenkohtaisesti. Anonyymit luokat voidaan määrittää menetelmällä, kuten seuraavasti:
public void DoSomething () { var henkilö = new { Nimi = "Marguerite" ; Ikä = 15 ; } var lemmikki = new { Nimi = "Dunya" ; Tyyppi = "kilpikonna" ; Omistaja = henkilö ; } konsoli . WriteLine ( " Lemmikin omistajan ikä : " + lemmikki . Omistaja . Ikä ); }Ruby-kielen luokat määritellään seuraavasti:
class MyClass def alustus # Constructor (valinnainen) end public # Julkinen tunniste on valinnainen, koska asetettu oletusarvoisesti # ilmaisee, että sitä seuraavat menetelmät ovat saatavilla mistä tahansa ohjelman kohdasta def public_method # Julkinen metodin loppu suojattu # Suojattu tunniste osoittaa, että seuraavat menetelmät # ovat vain tämän ja aliluokan jäsenten käytettävissä. def protected_method # Suojattu menetelmä loppu private # Yksityinen tunniste osoittaa, että seuraavat menetelmät # ovat vain tämän luokan jäsenten käytettävissä. def private_method # Yksityinen menetelmä end endLuokan esiintymän luominen:
objekti = Oma luokka . UusiLuokan ilmentymän tuhoaminen ei ole välttämätöntä: se tapahtuu automaattisesti "roskakeräimen" avulla heti, kun viimeinen viittaus siihen katoaa muistista.
Luokan määrittäminen Pythonissa käyttämällä operaattoria class:
class MyClass : def __init__ ( self , arg ): """Rakentaja""" self . _arg = arg # objektiparametri def method1 ( self , x ): """menetelmä sisältyy luokan käyttöliittymään""" def _method2 ( self , x ): """metodi, joka ei ole osa luokkaliittymää""" def __method2 ( self , x ): """menetelmä on käytettävissä vain luokassa""" @staticmethod def method3 ( arg1 , arg2 , ... ): """staattinen menetelmä, jota voidaan kutsua sekä luokan esiintymistä että itse luokasta""" @classmethod def method4 ( cls , arg1 , arg2 , ... ): """luokkamenetelmä, kutsuttavissa sekä luokan esiintymistä että itse luokasta, pääsy sisäisiin menetelmiin ja parametreihin"""Luokan esiintymän luominen:
myinstance = Omaluokka ( 4 )Luokkainstanssin eksplisiittistä tuhoamista ei vaadita, koska Pythonissa on automaattinen "roskankerääjä". Voit kuitenkin poistaa eksplisiittisesti viittauksen objektiin (luokan esiintymään tai itse luokkaan) seuraavasti:
minun esimerkkiniLuokan määrittäminen JavaScriptissä käyttämällä operaattoria class:
class MyClass { rakentaja ( arg1 , arg2 , ...) { //konstruktori (valinnainen) this . arg1 = arg1 ; tämä . arg2 = arg2 ; } menetelmä1 () { // Tavallinen menetelmä } staattinen menetelmä { // Staattinen menetelmä } }Luokan esiintymän luominen:
var myinstance = uusi MyClass ( 4 , 2 )Luokkainstanssin tuhoamista ei vaadita: se tapahtuu automaattisesti "roskakeräimen" avulla heti, kun viimeinen viittaus siihen katoaa muistista.
Jokainen Java-luokka luodaan yleensä erilliseen tiedostoon, tiedostonimen on vastattava luokan nimeä. Tässä tapauksessa se on MyClass.java
Java -luokan määrittäminen operaattorilla class:
Luokan esiintymän luominen:
MyClass my = uusi MyClass ( "Esimerkki 2" );"Roskatkeräjä" tuhoaa automaattisesti luokan esiintymän.
Tietotyypit | |
---|---|
Käsittämätön | |
Numeerinen | |
Teksti | |
Viite | |
Komposiitti | |
abstrakti | |
muu | |
liittyvät aiheet |