Marker interface , marker ( angl. marker interface pattern ) je návrhový vzor používaný v programovacích jazycích s kontrolou typu runtime . Šablona poskytuje možnost přidružit metadata (rozhraní) ke třídě, i když v jazyce neexistuje žádná explicitní podpora metadat.
Pro použití tohoto modelu třída implementuje rozhraní [1] ("označené rozhraním") a metody interagující s třídou kontrolují přítomnost rozhraní. Na rozdíl od běžného rozhraní , které definuje funkčnost (ve formě deklarací metod a vlastností), kterou musí implementovaná třída objektů mít, je důležitá skutečnost, že třída má značku. Značka je pouze znakem přítomnosti určitého chování v objektech třídy označené značkou. Samozřejmě jsou možná "smíšená" rozhraní, ale při neopatrném použití mohou způsobit zmatek.
Příkladem použití značek rozhraní v programovacím jazyce Java je rozhraní Serializable. Třída musí implementovat toto rozhraní, aby naznačila, že jeho instance lze zapisovat do ObjectOutputStream. Třída ObjectOutputStreammá veřejnou metodu writeObject(), která obsahuje řadu instanceofkontrol zapisovatelnosti, z nichž jednou je rozhraní Serializable. Pokud selže celá série kontrol, metoda vyvolá výjimku NotSerializableException.
Dalším příkladem je rozhraní INamingContainer , které je definováno v .NET Framework . INamingContainerdefinuje ovládací prvek kontejneru, který vytvoří nový identifikátor jmenného prostoru v hierarchii ovládacích prvků Page. [2] . Jakýkoli ovládací prvek, který implementuje toto rozhraní, vytvoří nový jmenný prostor, který zajistí, že všechna ID atributů podřízených ovládacích prvků budou v celé aplikaci jedinečná. Při navrhování ovládacích prvků podle šablony musíte implementovat toto rozhraní, abyste předešli konfliktům pojmenování na stránce.
Třída Repeaterje ovládací prvek seznamu vázaný na data, který je definován v rozhraní .NET Framework ( ASP.net ). Tento prvek umožňuje vytvořit označení opakováním zadaného vzoru pro každý prvek seznamu. Aby se předešlo konfliktům v názvech, je třída označena rozhraním INamingContainer.
veřejné rozhraní INamingContainer { } public class Control : IComponent , ... { ... internal bool IsBindingContainer { get { return (( toto je INamingContainer ) && !( toto je INonBindingContainer )); } } ... } public class opakovač : Control , INamingContainer { ... }Na základě vlastnosti přidá IsBindingContainer runtimeRepeater během generování stránky nový jmenný prostor k identifikátorům ovládacích prvků, které jsou v ovládacím prvku .
Výhodou použití značky je, že v jazycích, které nepodporují metadata , lze přidat další informace o chování třídy. Zároveň například v některých jazycích trvá extrahování informací z metadat déle, což při častém používání ovlivní výkon. Takže v jazyce C# můžete porovnat výkon konstrukce (a zkontrolovat, zda je podporováno nějaké chování nebo funkce), když je použito rozhraní značky:
ovládání je INamingContainera konstrukce pomocí atributů a reflexního mechanismu :
ovládání . Gettype (). IsDefined ( typeof ( NamingContainerAttrubute ), false )Kromě toho některé jazyky (například Java používající knihovny ASM, Javasistanebo podobné ; a další jazyky[ co? ] ) umožňují vytvářet nebo generovat třídy (a rozhraní) dynamickým označováním tříd rozhraním značek za běhu . Atributy nebo metadata jsou obvykle spojeny s třídami v době kompilace , takže je nemožné později změnit jejich chování.
Jedním z hlavních problémů markeru je to, že rozhraní definuje smlouvu o implementaci tříd a že smlouvu zdědí všechny podtřídy. To znamená, že pomocí značky nemůžete "vrátit zpět další implementace". Pokud ve výše uvedeném příkladu vytvoříte podtřídu a nechcete ji serializovat (možná proto, že to závisí na částečné implementaci), musíte explicitně vyvolat výjimku NotSerializableException(podle dokumentace ObjectOutputStream).
Řešením popsaného problému je podpora metadat přímo v syntaxi jazyka: