Konstruktor (objektum-orientált programozás)

Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt hozzászólók, és jelentősen eltérhet a 2016. június 28-án felülvizsgált verziótól ; az ellenőrzések 22 szerkesztést igényelnek .

Az objektumorientált programozásban az osztálykonstruktor (az angol konstruktor szóból  ) egy speciális utasításblokk, amelyet az objektum létrehozásakor hívnak meg.

Konstruktor hozzárendelés

Az OOP egyik legfontosabb jellemzője a beágyazás : az osztály belső mezői közvetlenül nem érhetők el, és a felhasználó csak az objektum egészével, nyilvános ( public) metódusokon keresztül tud dolgozni. Ideális esetben minden metódust úgy kell megtervezni, hogy egy "érvényes" állapotban lévő objektum (vagyis amikor az osztályinvariáns teljesül ) a metódus meghívásakor is érvényes állapotban legyen. A konstruktor első feladata pedig az, hogy az objektum mezőit ilyen állapotba vigye át.

A második feladat az objektum használatának egyszerűsítése. Egy objektum nem „ önmagában lévő dolog ”, gyakran bizonyos információkat kell kérnie más objektumoktól: például egy objektumnak Filelétre kell hoznia egy fájlnevet. Ez a következő módszerrel is megtehető:

fájl fájl ; fájl . open ( "in.txt" , Fájl :: omRead );

De kényelmesebb a fájl megnyitása a konstruktorban: [1]

Fájlfájl ( " in.txt " , Fájl :: omRead );

Konstruktorok típusai

A különféle programozási nyelvek többféle konstruktort kínálnak:

  • konstruktor paraméterekkel;
  • alapértelmezett konstruktor , amely nem vesz fel argumentumokat;
  • named constructor – olyan függvény, amely egy kifejezett név szerinti hívást feltételez, és úgy működik, mint egy konstruktor
  • copy konstruktor  - olyan konstruktor, amely argumentumként egy azonos osztályba tartozó objektumot (vagy hivatkozást) vesz fel;
  • konverziós konstruktor - egy konstruktor, amely egy argumentumot vesz fel (ezek a konstruktorok automatikusan meghívhatók más típusú értékek konvertálására ennek az osztálynak az objektumaivá).
  • konstruktor áthelyezése ( C++11 specifikus )
osztályú komplexum { nyilvános : // Alapértelmezett konstruktor // (ebben az esetben is konverziós konstruktor) Komplex ( double i_re = 0 , double i_im = 0 ) : re ( i_re ), im ( i_im ) {} // Összetett másolás konstruktor ( const Complex & obj ) { re = obj . re ; im = obj . im ; } privát : double re , im ; };

Konstruktor paraméterekkel

Azokat a konstruktorokat, amelyek egy vagy több argumentumot vesznek fel, paraméterezettnek nevezzük. Például:

osztályos példa { int x , y ; nyilvános : példa (); Példa ( int a , int b ); // paraméterezett konstruktor }; Példa :: Példa () { } Példa :: Példa ( int a , int b ) { x = a ; y = b ; }

Egy paraméterezett konstruktort lehet explicit vagy implicit módon meghívni, például:

e példa = példa ( 0 , 50 ); // kifejezett hívás e példa ( 0 , 50 ); // implicit hívás

Alapértelmezett konstruktor

Kötelező argumentumok nélküli konstruktor. Objektumtömbök létrehozásakor használatos, amelyek az egyes példányok létrehozására szolgálnak. Explicit alapértelmezett konstruktor hiányában a kódját a fordító generálja (ami természetesen nem jelenik meg a forrásszövegben).

Megnevezett konstruktor

Konstruktor másolása

Egy konstruktor, amelynek argumentuma egy azonos osztályba tartozó objektumra való hivatkozás . Használják a C++ -ban objektumok átadására a függvényeknek érték alapján .

A másoláskonstruktorra leginkább akkor van szükség, ha egy objektum a kupacban lefoglalt objektumokra mutat mutatókat . Ha a programozó nem hoz létre másoláskonstruktort, akkor a fordító létrehoz egy implicit másoláskonstruktort, amely a mutatókat úgy másolja, ahogy vannak , azaz nem történik meg az adatok tényleges másolása, és a két objektum ugyanarra az adatra hivatkozik a kupacban. Ennek megfelelően a „másolat” megváltoztatására tett kísérlet megsérti az eredetit, és az egyik objektum destruktorának meghívása a másik későbbi használatával olyan memóriaterülethez vezet, amely már nem tartozik a programhoz.

Az argumentumot hivatkozással kell átadni , nem érték szerint . Ez ütközésből következik: ha egy objektumot érték szerint adunk át (különösen a konstruktor meghívásához), az objektumot másolni kell. De egy objektum másolásához meg kell hívnia a másoláskonstruktort.

Konverziós konstruktor

Egy konstruktor, amely egy argumentumot vesz fel. Megadja az argumentum típuskonverzióját a konstruktor típusává. Ez a típuskonverzió csak akkor kerül alkalmazásra, ha egyedi.

A felhasználó által definiált típuskonverzió két formát ölthet: - C-típusból bármely T-típusba, amelyhez C-nek rendelkeznie kell egy C::operátorral T() - bármely T-típusból C-típusba, amelyhez C-ben a következőnek kell lennie: C::C(T) (vagy C::C(T&), vagy C::C(T&&))

Ha mindkét eset megengedett egy kifejezésben, akkor kétértelműség és fordítási hiba lép fel.

Ha egy konstruktort (vagy T() operátort) az explicit kulcsszóval jelölünk meg, akkor az ilyen típusú konverziót csak akkor alkalmazzuk, ha létezik (T)C vagy static_cast<T>C formájú explicit öntött művelet. Ha nincs kifejezett szó, akkor a fordító akár implicit módon is beilleszthet egy ilyen konverziót, például az f(T arg) függvény f(C) formában történő meghívásakor.

A mozgatható konstruktor

A C ++11 bevezeti a nem állandó hivatkozások új típusát, az rvalue  referenciát és a jelöléssel T&&, valamint egy újfajta konstruktort – a konstruktorok mozgatását .  A mozgatási konstruktor bemenetként egy osztályobjektumra mutató nem állandó hivatkozás értékét veszi fel, és az objektum erőforrásainak tulajdonjogát adja át. A Move konstruktorokat az ideiglenes objektumok létrehozásával járó hatékonyságveszteség megoldására találták ki.

Virtuális konstruktor

A konstruktor nem virtuális a virtuális metódus értelmében  – a virtuális metódusok mechanizmusának működéséhez le kell futtatnia a konstruktort, amely automatikusan beállítja az objektum virtuális metódustábláját .

A "virtuális konstruktorok" egy hasonló, de eltérő mechanizmusra utalnak, amely bizonyos nyelveken található, például a Delphiben , de nem a C++- ban és a Java -ban . Ez a mechanizmus lehetővé teszi bármely korábban ismeretlen osztály objektumának létrehozását két feltétel mellett:

  • ez az osztály valamilyen előre meghatározott osztály leszármazottja (ebben a példában ez egy osztály TVehicle);
  • a teljes öröklési úton az alaposztálytól a létrehozottig az újradefiníciós lánc nem szakadt meg. Virtuális metódus felülbírálásakor a Delphi szintaxis megköveteli a kulcsszót overload, hogy a régi és az új, eltérő aláírású függvények egymás mellett élhessenek, overrideakár a függvény felülbírálásához , akár reintroduceegy új, azonos nevű függvény definiálásához – ez utóbbi nem megengedett.
type TVehicle = osztály konstruktor Create ; virtuális ; vége ; TAutomobile = osztály ( TVehicle ) konstruktor Create ; felülbírálni ; vége ; TMotorcycle = osztály ( TVehicle ) konstruktor Create ; felülbírálni ; vége ; TMoped = osztály ( TMotorcycle ) // az újradefiniálási lánc megszakítása - új indítása Konstruktor létrehozása Create ( x : integer ) ; újra bevezetni ; vége ;

Bekerül a nyelvbe az úgynevezett osztálytípus ( metaclass ). Ez a típus felveheti értékként a -ból származó bármely osztály nevét TVehicle.

típus CVehicle = TVjármű osztály ; _

Ez a mechanizmus lehetővé teszi bármely korábban ismeretlen osztályból származó objektumok létrehozását TVehicle.

var cv : CJármű ; v : TVjármű ; cv := TAutomobile ; v := cv . létrehozni ;

Figyeld meg, hogy a kód

cv := TMoped ; v := cv . létrehozni ;

hibás - az irányelv reintroducemegszakította a virtuális metódus felülírásának láncát, és valójában a konstruktort hívják meg TMotorcycle.Create(ami azt jelenti, hogy egy motorkerékpárt hoznak létre, nem egy mopedet!)

Lásd még: Gyári (tervminta)

Szintaxis

C++

A konstruktor nevének meg kell egyeznie az osztály nevével. Több azonos nevű, de eltérő paraméterekkel rendelkező konstruktor megengedett .

Példa class ClassWithConstructor { nyilvános : /* A belső objektum inicializálása a konstruktorral */ ClassWithConstructor ( float paraméter ) : objektum ( paraméter ) {} /* konstruktor meghívása AnotherClass(float); */ privát : AnotherClass objektum ; };

Python

A Pythonban a konstruktor egy osztálymetódus, melynek neve __init__. Ne feledje továbbá, hogy bármely metódus első argumentumának az osztálykörnyezetre mutató mutatónak kell lennie self.

Példa osztály ClassWithConstructorral : def __init__ ( self ): """Ez a metódus konstruktor.""" pass

Ruby

A Ruby nyelv egy speciális módszerrel állítja be az objektumot a kezdeti konzisztens állapotába initialize.

Példa class ClassWithConstructor def inicializálás print 'Ez a metódus konstruktor.' vége vége

Delphi

A Delphiben a C++ -tól eltérően a konstruktor a kulcsszóval van deklarálva constructor. A konstruktor neve bármi lehet, de ajánlatos a konstruktort elnevezni Create.

Példa TClassWithConstructor = osztály nyilvános konstruktor Create ; vége ;

Java

Néhány különbség a konstruktorok és más Java metódusok között :

  • a konstruktoroknak nincs visszatérési típusuk (sőt, mindig ezt adják vissza);
  • a konstruktorok nem hívhatók meg közvetlenül (a kulcsszót kell használni new);
  • a konstruktoroknak nem lehetnek synchronized, final, abstractés módosítói native;static
Példa public class Példa { private int data ; // Alapértelmezett konstruktor, az adatok 1-re inicializálódnak, amikor a Példa osztály egy példányát létrehozzák public Példa () { data = 1 ; } // Konstruktor túlterhelés public Példa ( int input ) { data = input ; } } // egy objektum fent leírt konstruktor általi létrehozását illusztráló kód Példa e = new Példa ( 42 );

JavaScript

A JavaScriptben a konstruktor egy szabályos függvény, amelyet az operátor operandusaként használnak new. A kulcsszó a létrehozott objektumra utal this.

Az ECMAScript 6 specifikáció azonban hozzáadott egy prototípus szintaktikai wrappert, amely olyan OOP tulajdonságokkal rendelkezik , mint az öröklődés, valamint a szükséges metódusok egy kis listája, például: toString().

Példa function Példa ( initValue ) { this . myValue = initValue ; } példa . prototípus . getMyValue = function () { return this . myValue ; } //ES6 class class Példa { constructor () { console . log ( 'konstruktor' ); } } // kód, amely szemlélteti egy objektum létrehozását a fent leírt konstruktorral var exampleObject = new Példa ( 120 );

Visual Basic .NET

A Visual Basic .NET konstruktorai egy szabályos deklarációs metódust használnak New.

Példa Class Foobar Private strData As String ' Constructor Public Sub New ( ByVal someParam As String ) strData = someParam End Sub End Class ' néhány kód ', amely egy objektum létrehozását illusztrálja a fenti Dim foo As New Foobar ( ".NET" ) konstruktorral

C#

Példa class MyClass { privát int _szám ; privát karakterlánc _string ; public MyClass ( int szám , string str ) { _szám = szám ; _string = str ; } } // Az objektum fent leírt konstruktor általi létrehozását illusztráló kód MyClass példa = new MyClass ( 42 , "string" );

Eiffel

Az Eiffelben az objektumokat inicializáló rutinokat létrehozási eljárásoknak nevezzük . A létrehozási eljárások némileg hasonlóak a konstruktorokhoz, és némileg különböznek. A következő jellemzőkkel rendelkeznek:

  • A létrehozási eljárásoknak nincs kifejezett visszatérési eredménytípusa (az [1. megjegyzés] eljárás szerint ).
  • a létrehozási eljárások el vannak nevezve (a nevek érvényes azonosítókra korlátozódnak);
  • A létrehozási eljárásokat nevek határozzák meg az osztály szövegében;
  • létrehozási eljárások közvetlenül hívhatók (a normál eljárásokhoz hasonlóan) az objektumok újrainicializálásához;
  • minden hatékony (vagyis konkrét, nem absztrakt) osztálynak (explicit vagy implicit) meg kell határoznia legalább egy létrehozási eljárást;
  • A létrehozási eljárások felelősek azért, hogy az újonnan inicializált objektumot olyan állapotba hozzák, amely kielégíti az osztályinvariánst [2. megjegyzés] .

Bár az objektum létrehozása bizonyos finomságok tárgyát képezi [3. megjegyzés]x: T , egy attribútum létrehozása létrehozási utasításként kifejezett típusdeklarációval create x.makea következő lépésekből áll:

  • hozzon létre egy új közvetlen példányt a következő típusú T: [4. megjegyzés] ;
  • makehajtsa végre az újonnan létrehozott példány létrehozási eljárását ;
  • csatolja az újonnan létrehozott objektumot az entitáshoz x.
Példa

Az alábbi első rész meghatározza az osztályt POINT. Az eljárás makea kulcsszó után van kódolva feature.

A kulcsszó createbemutatja az osztály példányainak inicializálására használható eljárások listáját. Ebben az esetben a lista tartalmaz default_createegy eljárást, amelynek üres implementációja az osztályból örökölt ANY, és egy olyan eljárást make, amelynek megvalósítása magában az osztályban található POINT.

class POINT létre default_create , make funkció make ( a_x_érték : REAL ; a_y_érték : REAL ) do x := a_x_érték y := a_y_érték vége x : REAL -- X koordináta y : REAL -- Y koordináta ...

A második szakaszban az osztály kliensének számító osztálynak vannak típusú POINTdeklarációi . my_point_1my_point_2POINT

A szubrutin kódjában my_point_1a koordinátákkal (0.0; 0.0) jön létre. Mivel a létrehozási utasításban nincs megadva létrehozási eljárás, a rendszer default_createaz osztályból örökölt eljárást használja ANY. Ugyanez a sor átírható így create my_point_1.default_create. Csak a create eljárásként megadott eljárások használhatók a create utasításokban (vagyis a kulcsszóval rendelkező utasításokban create).

Ezután jön a létrehozási utasítás my_point_2, amely beállítja a koordináták kezdeti értékeit my_point_2.

A harmadik utasítás normál eljáráshívást hajt végre a különböző értékekkel makecsatolt példány újrainicializálására .my_point_2

my_point_1 : POINT my_point_2 : POINT ... saját_pont_1 létrehozása Saját_pont_2 létrehozása . make ( 3.0 , 4.0 ) my_point_2 . gyártmány ( 5.0 , 8.0 ) ...

Cold Fusion

Példa

Meg kell jegyezni, hogy a ColdFusionban nincs konstruktor módszer . A ColdFusion programozói közösségben elterjedt módszer a " " metódus initpszeudokonstruktorként való meghívása.

<cfcomponent displayname = "Sajt" > <!--- tulajdonságok ---> <cfset változók . cheeseName = "" / > <!--- pszeudokonstruktor ---> <cffunction name = "init" returntype = "Sajt" > <cfargument name = "cheeseName" type = "string" required = "true" / > <cfset változók . cheeseName = argumentumok . cheeseName / > <cfreturn this / > </cffunction> </cfcomponent>

PHP

Példa

A PHP -ben (5-ös verzió óta) a konstruktor egy olyan metódus __construct(), amelyet egy kulcsszó automatikusan meghív newaz objektum létrehozása után. Általában különféle automatikus inicializálások végrehajtására szolgál, például tulajdonság inicializálására. A konstruktorok argumentumokat is vehetnek, ebben az esetben egy kifejezés megadásakor newa formális paramétereket zárójelben kell átadni a konstruktornak.

class Személy { privát $név ; function __construct ( $name ) { $this -> name = $name ; } function getName () { return $this -> name ; } }

A PHP 4-es (és korábbi) verziójában azonban egy konstruktor ugyanazzal az osztálynévvel rendelkező osztálymetódus.

class Személy { privát $név ; function Személy ( $név ) { $this -> name = $name ; } function getName () { return $this -> name ; } }

Perl

Példa

Perlben a konstruktornak alkalmaznia kell a bless függvényt valamilyen változóra (általában egy hash hivatkozásra):

csomag Példa ; sub new { my $class = shift ; én $én = {}; return bless $self , $class ; } 1 ;

De ez a minimális alap opció, sok fejlettebb módszer létezik, a használati mezőktől a Moose-ig.

Egyszerűsített konstruktorok ( pszeudokóddal )

A konstruktorok mindig részei az osztályok megvalósításának. Az osztály (a programozásban) az osztályba tartozó objektumok halmazának alapvető jellemzőinek specifikációit írja le, nem pedig bármelyik objektum egyedi jellemzőit. Nézzünk egy egyszerű analógiát. Vegyünk példának egy adott iskola tanulóinak halmazát (vagy osztályát, hogy általánosabb jelentését használjuk). Így rendelkezünk:

osztályos tanuló { // a tanulói osztály leírása // ... másik kód ... }

Az óra azonban Student csak egy általános sablon (prototípus) diákjaink számára. Használatához a programozó minden tanulót objektumként vagy entitásként ( implementációként ) hoz létre az osztályban. Ez az objektum az a valós adat a memóriában, amelynek méretét, mintáját, jellemzőit és (bizonyos mértékben) viselkedését az osztálydefiníció határozza meg. Az objektumok létrehozásának szokásos módja egy konstruktor meghívása (az osztályoknak általában lehetnek külön konstruktorai). Például,

osztályos tanuló { Tanuló(karakterlánc diáknév, karakterlánc-cím, int azonosító) { // ... itt tároljuk a bemeneti adatokat és egyéb belső mezőket ... } // ... }

Lásd még

Jegyzetek

  1. Az Eiffel szubrutinok vagy eljárások vagy függvények . Az eljárásoknak nincs visszaküldési típusa. A függvényeknek mindig van visszatérési típusa.
  2. Mivel az örökölt osztály(ok) invariánsának is teljesülnie kell, nincs kötelező előírás a szülő konstruktorok meghívására.
  3. A teljes specifikációt az Eiffel programozási nyelvre vonatkozó ISO/ECMA szabvány tartalmazza, amely online elérhető. [2]
  4. Az Eiffel-szabvány megköveteli a mezők inicializálását az első hozzáféréskor, beleértve a mezőket. nincs szükség alapértelmezett értékekkel inicializálni őket az objektum létrehozásakor.

Linkek

  1. Természetesen ez bizonyos technikai nehézségekhez vezet – például mi történik, ha kivételt dob ​​a konstruktor ? Az osztályfejlesztőnek azonban egyszerűen meg kell felelnie a nyelv követelményeinek, és a legtöbb program nem igényel részletes diagnosztikát és automatikus hibakeresést.
  2. ISO/ECMA Eiffel-leíró dokumentum . Letöltve: 2009. április 19. Az eredetiből archiválva : 2008. június 16..