Osztály - az objektumorientált programozásban , egy modell bizonyos típusú objektumok létrehozására , szerkezetük leírására (mezők halmaza és kezdeti állapota), valamint algoritmusok (függvények vagy metódusok ) meghatározása az objektumokkal való munkavégzéshez.
Más szóval, egy osztály eszközként szolgál absztrakt adattípusok szoftverprojektbe való beépítéséhez. Az absztrakt adattípusok egyéb leírói - metaosztályok , interfészek , struktúrák , felsorolások - saját jellemzőkkel rendelkeznek. Az osztályok közötti különbség lényege, hogy egy adattípus megadásakor egy osztály minden példányához (azaz objektumához) egyszerre definiál interfészt és implementációt is, így a konstruktor metódus meghívása kötelező.
Az osztály az egyik kulcsfogalom az OOP -ban, de vannak osztály nélküli objektumorientált nyelvek is, például Self , JavaScript , Lua , (további részletekért lásd: Prototípus programozás ).
A gyakorlatban az objektum-orientált programozás számos osztály létrehozását jelenti, beleértve egy interfészt és egy implementációt, majd ezeket használja. Számos osztály és a köztük lévő kapcsolatok grafikus ábrázolását osztálydiagramnak nevezzük . Az objektum-orientált megközelítés fejlesztése során rengeteg ajánlást ( mintát ) halmozott fel osztályok és osztályhierarchiák létrehozására .
Az órák ötlete a mesterséges intelligencia kutatása szempontjából releváns tudásbázis munkából származik. Az ember által a zoológiában, botanikában, kémiában, gépalkatrészekben használt osztályozások azt az alapgondolatot hordozzák, hogy minden dolog mindig ábrázolható valamilyen általánosabb fogalom speciális eseteként. Egy adott alma általában egy alma, egy alma általában, és minden alma általában egy gyümölcs. (Az alma és a körte az objektumorientált programozási oktatóanyagok osztályainak gyakori példája.)
Az alábbiakban mindenhol az „osztály”, „ objektum ”, „ interfész ” és „ struktúra ” szavakat az OOP-ban megadott speciális jelentésükben használjuk.
Az osztályokat használó objektumorientált programokban minden objektum egy adott osztály " példánya ", és nincs más objektum. Vagyis az „ egy osztály példánya ” ebben az esetben nem „egy osztály példáját” vagy „egyetlen osztályt” jelenti, hanem „olyan objektumot, amelynek típusa valamilyen osztály”. Ugyanakkor a különböző programozási nyelvekben megengedett vagy nem megengedett néhány más adattípus létezése, amelyek példányai nem objektumok (vagyis a nyelv határozza meg, hogy a számok, tömbök és mutatók objektumok-e, ill. nem, és ennek megfelelően, hogy vannak-e olyan osztályok, mint a "szám", "tömb" vagy "mutató", amelyeknek minden egyes szám, tömb vagy mutató példánya lenne).
Például a "szövegsor" absztrakt adattípus osztályként tervezhető, és akkor a program minden szövegsora objektum lesz - a "szövegsor" osztály példányai.
Osztályok használatakor a programkód minden eleme, mint például a változók, konstansok, metódusok, eljárások és függvények, tartozhat (és sok nyelvben tartoznia kell) egyik vagy másik osztályhoz. Magát az osztályt végső soron tagjainak listájaként határozzák meg , nevezetesen mezők ( tulajdonságok ) és metódusok/függvények/eljárások . A programozási nyelvtől függően konstansok, attribútumok és külső definíciók is hozzáadhatók ehhez a listához.
A struktúrákhoz hasonlóan az osztályok is meghatározhatnak mezőket – vagyis olyan változókat, amelyek vagy közvetlenül az osztályhoz tartoznak (statikus), vagy az osztály példányaihoz (közönséges). A statikus mezők egy példányban léteznek a teljes programhoz (vagy összetettebb változat esetén folyamatonként vagy szálonként/szálonként egy példányban ). A közönséges mezők egy példányban jönnek létre minden egyes objektumhoz - az osztály egy példányához. Például a programban a működése során létrehozott szövegsorok teljes száma a "szövegsor" osztály statikus mezője lesz. És egy karakterlánc meghatározott karaktertömbje a "string of text" osztály egy példányának szabályos mezője lesz, ahogyan a "szövegkarakterlánc" típusú "vezetéknév" változó is minden konkrét példány szabályos mezője lesz. a "személy" osztályból.
Az OOP-ban osztályok használatakor az összes végrehajtható programkód (algoritmus) úgynevezett "metódusok", "függvények" vagy "eljárások" formájában jelenik meg, ami megfelel a hagyományos strukturált programozásnak , de most már megtehetik (és sok nyelvnek kell egyik vagy másik osztályhoz tartoznia. Például, ha lehetséges, a "szövegkarakterlánc" osztály tartalmazza az összes olyan alapvető metódust/függvényt/eljárást, amelyet a szöveggel való munkára terveztek, mint például a keresést egy karakterláncban, egy karakterlánc egy részének kivágását stb.
A mezőkhöz hasonlóan az osztályhoz tartozó metódusok/függvények/eljárások formájában megjelenő kód magára az osztályra vagy az osztály példányaira vonatkoztatható. Egy osztályhoz tartozó és az osztályhoz társított metódus (statikus metódus) önmagában is meghívható, és hozzáférhet az osztály statikus változóihoz. Egy osztálypéldányhoz társított metódus (közönséges metódus) csak magán az objektumon hívható meg, és hozzáfér mind az osztály statikus mezőihez, mind egy adott objektum szabályos mezőihez (ha meghívják, ez az objektum mint rejtett metódus paraméter). Például a létrehozott karakterláncok teljes számát bárhonnan megtalálhatjuk a programban, de egy adott karakterlánc hosszát csak úgy lehet megtalálni, ha valamilyen módon megadjuk, hogy melyik karakterlánc hosszát mérjük.
A programozásban létezik a programozói interfész fogalma, ami azon lehetséges számítások listáját jelenti, amelyeket a program egyik vagy másik része el tud végezni. Ez tartalmazza a leírást: milyen argumentumokat és milyen sorrendben kell átadni a listából az algoritmusok bemenetére, valamint azt, hogy azok mit és milyen formában fognak visszaadni. Az absztrakt adattípusú interfészt egy ilyen lista formalizált leírására találták ki. Magukat az algoritmusokat, vagyis a tényleges programkódot, amely mindezeket a számításokat elvégzi, nem határozza meg az interfész, külön programozzák őket, és az interfész megvalósításának nevezzük .
A programozási interfészek, valamint az osztályok kiterjeszthetők az öröklődés révén , amely az OOP kód újrafelhasználásának egyik fontos eszköze. Egy örökölt osztály vagy interfész mindent tartalmaz, ami az összes szülőosztályához meg van adva (programozási nyelvtől és platformtól függően nullától a végtelenig lehet). Például létrehozhat egy szöveges karakterlánc saját verzióját úgy, hogy a „szövegkarakterlánc” osztályt a már meglévő „szövegkarakterlánc” osztályból örökli, miközben feltételezzük, hogy a programozónak nem kell átírnia a keresési algoritmusokat és így tovább. mivel ezek automatikusan öröklődnek a kész osztályból, és a „szövegsorom” osztály bármely példánya nem csak a „szövegsor” szülőosztály kész metódusainak adható át a szükséges számítások elvégzésére, hanem általános minden olyan algoritmusra, amely képes dolgozni „szövegsor” típusú objektumokkal, mivel mindkét osztály példányai kompatibilisek egymással.
Az osztály lehetővé teszi, hogy ne csak a programozási felületet állítsa be önmagára és példányaira, hanem kifejezetten megírja a számításokért felelős kódot is. Ha az új adattípusunk létrehozásakor örököljük a felületet, akkor az adattípusunk egy példányát át tudjuk adni bármely olyan algoritmusnak, amely képes együttműködni ezzel a felülettel. Az interfész megvalósítását azonban magunknak kell megírnunk, vagyis azokat az algoritmusokat, amelyekkel a számunkra érdekes algoritmus számításokat végez a példányunk segítségével. Ugyanakkor egy osztály öröklésével automatikusan örököljük az interfész kész kódját (ez nem mindig van így, a szülő osztály megkövetelheti néhány algoritmus megvalósítását a gyermekosztályban hiba nélkül). Ez a kódból való öröklési képesség egyértelművé teszi, hogy egy objektum-orientált programban egy osztály adattípusa egy interfészt és egy implementációt is meghatároz minden példányához.
A strukturált programozás egyik problémája, amellyel az OOP küzd, a programváltozók helyes értékének fenntartása. Gyakran a különböző programváltozók logikailag összefüggő értékeket tárolnak, és ennek a logikai kapcsolatnak a fenntartásáért a programozó felelős, vagyis a kapcsolat nem kerül automatikusan karbantartásra. Példa erre a „kirúgva” és az „év végén bónuszra számít” zászló, amikor a személyzeti osztály szabályai szerint egyszerre lehet nem elbocsátani és nem számíthat bónuszra, nem kirúgni és várni. bónusz, kirúgva, és nem vár bónuszt, de nem lehet egyszerre kirúgni és bónuszra vár. Ez azt jelenti, hogy a program bármely részének, amely bejelöli a "kirúgott" jelölőnégyzetet, mindig törölnie kell a pipát az "év végi bónuszokra vár" négyzetből.
A probléma megoldásának jó módja, ha a "kirúgott" jelzőt megváltoztathatatlanná tesszük a program minden részében, kivéve egy konkrétan meghatározottat. Ebben a konkrét részben minden egyszer és helyesen lesz írva, és mindenki másnak erre a szakaszra kell hivatkoznia, amikor be akarja jelölni vagy törölni akarja a "kirúgott" négyzetet.
Egy objektum-orientált programban a "kigyújtott" jelzőt valamelyik osztály privát tagjának nyilvánítják, és a megfelelő nyilvános metódusokat írják az olvasáshoz és módosításhoz. Azokat a szabályokat, amelyek meghatározzák a változók közvetlen megváltoztatásának lehetőségét vagy lehetetlenségét, hozzáférési hatókör beállításának szabályainak nevezzük. A "privát" és a "nyilvános" szavak ebben az esetben az úgynevezett " hozzáférés-módosítók ". Módosítóknak nevezik őket, mert bizonyos nyelveken a korábban beállított engedélyek megváltoztatására használják, amikor egy osztály öröklődik. Az osztályok és a hozzáférés-módosítók együttesen határoznak meg egy hozzáférési területet, azaz a kód minden szakasza, attól függően, hogy melyik osztályba tartozik, saját hozzáférési területtel rendelkezik az osztály és más osztályok bizonyos elemei (tagjai), beleértve a változókat is. , metódusok, függvények , konstansok stb. Van egy alapszabály: az egyik osztályban semmi sem láthatja egy másik osztály privát tagjait. Más, összetettebb szabályokkal kapcsolatban a különböző nyelvek eltérő hozzáférés-módosítókkal és szabályokkal rendelkeznek az osztályokkal való interakcióra vonatkozóan.
Szinte minden osztálytaghoz be lehet állítani hozzáférésmódosítót (kivéve a statikus konstruktorokat és még néhány dolgot). A legtöbb objektum-orientált programozási nyelv támogatja a következő hozzáférés-módosítókat:
A változók helyes állapotának megőrzésének problémája is aktuális a kezdeti értékek beállításának legelső pillanatában. Ehhez az osztályok speciális metódusokat/függvényeket biztosítanak, amelyeket konstruktoroknak nevezünk. Semmilyen objektum (egy osztály példánya) nem hozható létre másként, mint a konstruktor kódjának végrehajtásra történő meghívásával, amely visszaküldi a hívónak az osztály egy létrehozott és megfelelően feltöltött példányát. Sok programozási nyelvben a „struct” adattípus, akárcsak egy osztály, tartalmazhat változókat és metódusokat, de a struktúrák példányai, amelyek csak a RAM megjelölt területe maradnak, létrehozhatók a konstruktorok megkerülésével, ami az osztálypéldányoknál tilos ( kivéve az egyes nyelveken és platformokon biztosított összes hasonló OOP-szabály megkerülésére szolgáló különleges kivételes módszereket). Ez megmutatja az osztályok és más adattípusok közötti különbséget – konstruktorhívás szükséges.
A modern objektum-orientált programozási nyelvekben (beleértve a php , Java , C++ , Oberon , Python , Ruby , Smalltalk , Object Pascal ) egy osztály létrehozása a mezőket és metódusokat (ez utóbbiak között a konstruktorokat) tartalmazó struktúra megírásával jár. különleges szerepet játszanak, destruktorok, véglegesítők). A gyakorlatban egy osztály felfogható sablonként, amely szerint objektumok jönnek létre - ennek az osztálynak a példányai. Ugyanannak az osztálynak az összes példánya ugyanazon sablon szerint jön létre, így ugyanazokkal a mezőkkel és metódusokkal rendelkeznek.
Az osztálytagok hatóköre (azaz az a kód hatóköre, ahonnan minősíthetetlen néven elérhetők - az osztály vagy objektum nevének megadása nélkül) nem függ a hatókörüktől, és mindig megegyezik az osztály kódjával. osztályú módszerek.
Magának az osztálynak a hatóköre a különböző programozási nyelvekben eltérően van meghatározva. Egyes nyelveken (pl. Delphi ) minden osztálynak van globális láthatósága (figyelembe véve a modul láthatóságát ), másokban (mint például a Java ) az osztály hatóköre az azt tartalmazó fordítási egységhez van társítva (Java nyelven). - csomaggal ), másokban (például C ++ és C# ) egy osztály hatókörét névterek ( névterek ) határozzák meg, amelyeket a programozó kifejezetten beállít, és előfordulhat, hogy egyezik a fordítási egységekkel.
A Delphiben az osztály leírása a következő:
TMyClass = class ( TObject ) private {Az ebben a részben leírt elemek kívülről (az osztályon kívülről, de a modulon belül elérhetők) nem érhetők el.} {Az osztálymezők általában itt találhatók.} szigorú privát {Delphi 2007 és újabb verziókhoz. Az ebben a részben leírt elemek csak az osztályon belül érhetők el} védett {Az ebben a szakaszban leírt elemek csak az osztály és annak összes leszármazottja számára érhetők el.} public {Az ebben a részben leírt elemek mindenki számára elérhetők.} közzétéve {Az ebben leírt elemek szakasz mindenki számára elérhető, és az Object Inspector'e.} end ;Az osztály példánya (objektuma) a következőképpen jön létre:
MyClass := TMyClass . létrehozni ;Így megsemmisítve:
FreeAndNil ( MyClass ) ; VAGY MyClass . Ingyenes ;A C++- ban a következőképpen jön létre egy osztály :
class MyClass : public ParentClass // ParentClass - ősosztály, ha van { nyilvános : // ebben a szakaszban az elemek a program bármely részéből elérhetők MyClass (); // konstruktor ~ MyClass (); // destruktor védett : // ebben a szakaszban az elemek elérhetők az osztályból és leszármazottaiból : // ebben a szakaszban az elemek csak az osztályból érhetők el; ez az alapértelmezett hatókör };A létrehozást követően egy osztály teljes értékű adattípusnak minősül , ezért az osztály példányai a következők szerint jönnek létre:
MyClass énpéldány ;Az osztály tagjainak hívása:
az én példám . osztályos tagAz osztály egy példánya, mint minden változó, csak akkor semmisül meg, ha az a függvény , amelyben létrehozták, befejezte a munkáját, vagy ha az osztályhoz lefoglalt dinamikus memória erőszakkal fel lett szabadítva .
A C# osztályok meghatározása a következő:
public class MyClass { //A program bármely osztálya számára elérhető tag public int k ; //A tag bármely osztály számára elérhető ugyanabban a programmodulban belső int l ; //A tag bármely osztály számára elérhető ugyanabban a programmodulban, vagy csak az aktuális osztályhoz és annak összes alosztályához egy másik modulban védett belső int m ; //Csak az aktuális osztály és annak összes alosztálya számára elérhető tag int n ; //A tag csak az aktuális osztályból érhető el (alapértelmezett). private int fg ; }A C++-tól eltérően a hozzáférés-módosítókat tagonként kell megadni. Az anonim osztályok definiálhatók egy ilyen módszerrel:
public void DoSomething () { var person = new { Név = "Marguerite" ; Életkor = 15 ; } var pet = new { Név = "Dunya" ; Type = "teknős" ; Tulajdonos = személy ; } Konzol . WriteLine ( "A kisállat tulajdonosának életkora: " + kisállat . Tulajdonos . Életkora ); }A Ruby nyelv osztályai a következők:
class MyClass def inicializálás # Konstruktor (opcionális) vége public # A nyilvános azonosító nem kötelező, mert alapértelmezés szerint a # azt jelzi, hogy az őt követő metódusok bárhonnan elérhetők a programban def public_method # Public metódus vége protected # A védett azonosító azt jelzi, hogy a következő metódusok # csak ennek és a gyermekosztály tagjainak lesznek elérhetők def protected_method # Protected metódus vége private # A privát azonosító azt jelzi, hogy a következő metódusok # csak ennek az osztálynak a tagjai lesznek elérhetők def private_method # Privát metódus vége végeEgy osztály példányának létrehozása:
object = MyClass . újEgy osztály példányának megsemmisítése nem kötelező: ez automatikusan megtörténik a "szemétgyűjtő" használatával, amint az utolsó hivatkozás eltűnik a memóriából.
Osztály meghatározása Pythonban az operátor segítségével class:
class MyClass : def __init__ ( self , arg ): """Konstruktor""" self . _arg = arg # objektumparaméter def method1 ( self , x ): """metódus szerepel az osztály interfészében""" def _method2 ( self , x ): """egy metódus, amely nem része egy osztályfelületnek""" def __method2 ( self , x ): """a módszer csak az osztályon belül érhető el""" @staticmethod def method3 ( arg1 , arg2 , ... ): """egy statikus metódus, amely az osztály példányaiból és magából az osztályból is meghívható""" @classmethod def method4 ( cls , arg1 , arg2 , ... ): """osztály metódus, hívható az osztály példányaiból és magából az osztályból is, belső metódusokhoz és paraméterekhez való hozzáféréssel"""Egy osztály példányának létrehozása:
saját példány = MyClass ( 4 )Az osztálypéldány kifejezett megsemmisítése nem szükséges, mivel a Pythonnak van egy automatikus "szemétgyűjtője". Azonban kifejezetten eltávolíthat egy objektumra (egy osztály példányára vagy magára az osztályra) való hivatkozást, például:
del myinstanceOsztály meghatározása JavaScriptben az operátor segítségével class:
class MyClass { konstruktor ( arg1 , arg2 , ...) { //constructor (opcionális) this . arg1 = arg1 ; ezt . arg2 = arg2 ; } 1. módszer () { // Szokásos módszer } statikus metódus { // Statikus módszer } }Egy osztály példányának létrehozása:
var myinstance = new MyClass ( 4 , 2 )Egy osztálypéldány megsemmisítése nem szükséges: ez automatikusan megtörténik a "szemétgyűjtő" használatával, amint az utolsó hivatkozás eltűnik a memóriából.
A Java-ban minden osztály általában külön fájlban készül, a fájl nevének meg kell egyeznie az osztály nevével. Ebben az esetben a MyClass.java lesz
Java osztály meghatározása az operátor segítségével class:
Egy osztály példányának létrehozása:
MyClass my = new MyClass ( "2. példa" );Egy osztály példányát a "szemétgyűjtő" automatikusan megsemmisíti.
Adattípusok | |
---|---|
Értelmezhetetlen | |
Numerikus | |
Szöveg | |
Referencia | |
Összetett | |
absztrakt | |
Egyéb | |
Kapcsolódó témák |