Třídní invariant

V programování , konkrétně objektově orientovaném programování , je invariant třídy (nebo invariant typu ) invariant používaný k omezení objektů třídy. Metody třídy musí zachovat invariant.

Během vytváření tříd jsou stanoveny jejich invarianty, které jsou neustále udržovány mezi voláními veřejných metod. Dočasné narušení invariance třídy mezi vyvoláním soukromých metod je možné, i když není žádoucí.

Invariant objektu je programovací konstrukce sestávající ze sady invariantních vlastností. To zajišťuje, že objekt bude vždy odpovídat předem definovaným podmínkám, a tak se metody mohou vždy odkazovat na objekt bez rizika vytváření nepřesných předpokladů. Definování invariantů tříd může pomoci programátorům a testerům najít více chyb při testování softwaru.

Třídní invarianty a dědičnost

Užitečný efekt třídních invariantů v objektově orientovaném programování je vylepšen přítomností dědičnosti. Invarianty třídy se dědí, to znamená, že invarianty všech rodičů třídy se vztahují na třídu samotnou. [jeden]

Dědičnost umožňuje podřízeným třídám měnit implementační data nadřazených tříd, takže podřízená třída může změnit stav instancí způsobem, který je z pohledu nadřazené třídy činí neplatnými. Odkazování na tento neplatný podřízený typ je jedním z důvodů, proč vývojáři objektově orientovaného softwaru upřednostňují zapouzdření před dědičností. [2]

Protože se však invarianty třídy dědí, invariant třídy pro libovolnou konkrétní třídu sestává z jakýchkoli invariantních příkazů zakódovaných přímo v této třídě v kombinaci se všemi invariantními klauzulemi zděděnými od rodičů této třídy. To znamená, že zatímco podřízené třídy mohou přistupovat k datům implementace svých rodičů, invariant třídy jim může zabránit v manipulaci s těmito daty jakýmkoli způsobem, který vytvoří neplatnou instanci za běhu.

Podpora programovacího jazyka

Výpisy

Programovací jazyky jako C++ a Java podporují výchozí výrazy , které lze použít k definování invariantů třídy. Běžným příkladem implementace invariantů ve třídách je, že konstruktor třídy vyvolá výjimku, pokud invariant není splněn. Protože metody zachovávají invarianty, mohou přijmout platnost invariantu a nemusejí jej explicitně kontrolovat.

Nativní podpora

Invariant třídy je základní složkou smluvního programování . Programovací jazyky, které poskytují plnou podporu pro smluvní programování, jako je Eiffel , Ada a D , tedy budou také poskytovat plnou podporu pro invarianty tříd.

Nenativní podpora

Java má výkonnější nástroj nazvaný Java Modeling Language , který poskytuje robustnější způsob, jak definovat invarianty tříd.

Příklady

Nativní podpora

D

Programovací jazyk D má vestavěnou podporu pro invarianty třídy, stejně jako další smluvní programovací techniky. Zde je příklad z oficiální dokumentace.

třída Datum { int den ; int hodina ; invariantní () { tvrdit ( 1 <= den && den <= 31 ); tvrdit ( 0 <= hodina && hodina < 24 ); } } Eiffel

V Eiffelovi je invariant třídy deklarován na konci třídy za klíčovým slovem.

třída DATUM vytvořit make feature { NONE } -- Inicializace make ( a_day : INTEGER ; a_hour : INTEGER ) -- Inicializujte 'Current' pomocí 'a_day' a 'a_hour'. vyžadovat platný_den : 1 <= a_day a a_day <= 31 valid_hour : 0 <= a_hour and a_hour <= 23 do day := a_day hour := a_hour zajistit day_set : day = a_day hour_set : hour = a_hour end funkce -- Přístup den : INTEGER -- Den v měsíci pro 'Aktuální' hodina : INTEGER -- hodina dne pro 'Aktuální' feature -- Změna prvku set_day ( a_day : INTEGER ) -- Set `day' to `a_day' required valid_argument : 1 < = a_day and a_day <= 31 do day := a_day secure day_set : day = a_day end set_hour ( a_hour : INTEGER ) – Nastavit `hour' na `a_hour' vyžaduje platný_argument : 0 <= a_hour a a_hour <= 23 do hour := a_hour zajistit hour_set : hour = a_hour end invariant valid_day : 1 <= den a den <= 31 valid_hour : 0 <= hodina a hodina <= 23 konec

Nenativní podpora

Java

Toto je příklad invariantu třídy v programovacím jazyce Java s jazykem Java Modeling Language. Invariant musí být pravdivý po dokončení konstruktoru a při vstupu a výstupu všech členů veřejné funkce, která musí definovat předběžnou a následnou podmínku pro vynucení invariantu třídy.

public class Datum { int /*@spec_public@*/ den ; int /*@spec_public@*/ hodina ; /*@invariant 1 <= den && den <= 31; @*/ //invariant třídy /*@invariant 0 <= hodina && hodina < 24; @*/ //třída invariant /*@ @ vyžaduje 1 <= d && d <= 31; @vyžaduje 0 <= h && h < 24; @*/ public Date ( int d , int h ) { // den konstruktoru = d ; hodina = h ; } /*@ @ vyžaduje 1 <= d && d <= 31; @zajišťuje den == d; @*/ public void setDay ( int d ) { den = d ; } /*@ @ vyžaduje 0 <= h && h < 24; @zajišťuje hodinu == h; @*/ public void setHour ( int h ) { hour = h ; } }

Poznámky

  1. Bertrand Meyer. Objektově orientovaná softwarová konstrukce . - 2. vyd. - 1997. - S.  570 .
  2. E. Gamma, R. Helm, R. Johnson a J. Vlissides. Návrhové vzory: Prvky opakovaně použitelného objektově orientovaného softwaru. - 1995. - S. 20.