description | title | ms.date | ms.topic | helpviewer_keywords | ms.assetid | ||
---|---|---|---|---|---|---|---|
Learn more about: Generic Interfaces (C++/CLI) | Generic Interfaces (C++/CLI) | 10/12/2018 | reference |
| f3da788a-ba83-4db7-9dcf-9b95a8fb9d1a |
The restrictions that apply to type parameters on classes are the same as those that apply to type parameters on interfaces (see Generic Classes (C++/CLI)).
The rules that control function overloading are the same for functions within generic classes or generic interfaces.
Explicit interface member implementations work with constructed interface types in the same way as with simple interface types (see the following examples).
For more information on interfaces, see interface class.
[attributes] generic <class-key type-parameter-identifier[, ...]> [type-parameter-constraints-clauses][accesibility-modifiers] interface classidentifier [: base-list] { interface-body} [declarators] ;
attributes
(Optional) Additional declarative information. For more information on attributes and attribute classes, see Attributes.
class-keyclass
or typename
type-parameter-identifier(s)
Comma-separated identifiers list.
type-parameter-constraints-clauses
Takes the form specified in Constraints on Generic Type Parameters (C++/CLI)
accessibility-modifiers
(Optional) Accessibility modifiers (e.g. public, private).
identifier
The interface name.
base-list
(Optional) A list that contains one or more explicit base interfaces separated by commas.
interface-body
Declarations of the interface members.
declarators
(Optional) Declarations of variables based on this type.
The following example demonstrates how to declare and instantiate a generic interface. In the example, the generic interface IList<ItemType>
is declared. It is then implemented by two generic classes, List1<ItemType>
and List2<ItemType>
, with different implementations.
// generic_interface.cpp// compile with: /clrusingnamespaceSystem;// An exception to be thrown by the List when// attempting to access elements beyond the// end of the list. ref classElementNotFoundException : Exception {}; // A generic List interface generic <typename ItemType> public interface classIList { ItemType MoveFirst(); boolAdd(ItemType item); boolAtEnd(); ItemType Current(); voidMoveNext(); }; // A linked list implementation of IList generic <typename ItemType> public ref classList1 : publicIList<ItemType> { ref classNode { ItemType m_item; public: ItemType get_Item() { return m_item; }; voidset_Item(ItemType value) { m_item = value; }; Node^ next; Node(ItemType item) { m_item = item; next = nullptr; } }; Node^ first; Node^ last; Node^ current; public:List1() { first = nullptr; last = first; current = first; } virtual ItemType MoveFirst() { current = first; if (first != nullptr) return first->get_Item(); elsereturnItemType(); } virtualboolAdd(ItemType item) { if (last != nullptr) { last->next = gcnew Node(item); last = last->next; } else { first = gcnew Node(item); last = first; current = first; } returntrue; } virtualboolAtEnd() { if (current == nullptr ) returntrue; elsereturnfalse; } virtual ItemType Current() { if (current != nullptr) return current->get_Item(); elsethrow gcnew ElementNotFoundException(); } virtualvoidMoveNext() { if (current != nullptr) current = current->next; elsethrow gcnew ElementNotFoundException(); } }; // An array implementation of IList generic <typename ItemType> ref classList2 : publicIList<ItemType> { array<ItemType>^ item_array; int count; int current; public:List2() { // not yet possible to declare an// array of a generic type parameter item_array = gcnew array<ItemType>(256); count = current = 0; } virtual ItemType MoveFirst() { current = 0; return item_array[0]; } virtualboolAdd(ItemType item) { if (count < 256) item_array[count++] = item; elsereturnfalse; returntrue; } virtualboolAtEnd() { if (current >= count) returntrue; elsereturnfalse; } virtual ItemType Current() { if (current < count) return item_array[current]; elsethrow gcnew ElementNotFoundException(); } virtualvoidMoveNext() { if (current < count) ++current; elsethrow gcnew ElementNotFoundException(); } }; // Add elements to the list and display them. generic <typename ItemType> voidAddStringsAndDisplay(IList<ItemType>^ list, ItemType item1, ItemType item2) { list->Add(item1); list->Add(item2); for (list->MoveFirst(); ! list->AtEnd(); list->MoveNext()) Console::WriteLine(list->Current()); } intmain() { // Instantiate both types of list. List1<String^>^ list1 = gcnew List1<String^>(); List2<String^>^ list2 = gcnew List2<String^>(); // Use the linked list implementation of IList. AddStringsAndDisplay<String^>(list1, "Linked List", "List1"); // Use the array implementation of the IList. AddStringsAndDisplay<String^>(list2, "Array List", "List2"); }
Linked List List1 Array List List2
This example declares a generic interface, IMyGenIface
, and two non-generic interfaces, IMySpecializedInt
and ImySpecializedString
, that specialize IMyGenIface
. The two specialized interfaces are then implemented by two classes, MyIntClass
and MyStringClass
. The example shows how to specialize generic interfaces, instantiate generic and non-generic interfaces, and call the explicitly implemented members on the interfaces.
// generic_interface2.cpp// compile with: /clr// Specializing and implementing generic interfaces.usingnamespaceSystem; generic <classItemType> public interface classIMyGenIface { voidInitialize(ItemType f); }; public interface classIMySpecializedInt: publicIMyGenIface<int> { voidDisplay(); }; public interface classIMySpecializedString: publicIMyGenIface<String^> { voidDisplay(); }; public ref classMyIntClass: publicIMySpecializedInt { int myField; public:virtualvoidInitialize(int f) { myField = f; } virtualvoidDisplay() { Console::WriteLine("The integer field contains: {0}", myField); } }; public ref structMyStringClass: IMySpecializedString { String^ myField; public:virtualvoidInitialize(String^ f) { myField = f; } virtualvoidDisplay() { Console::WriteLine("The String field contains: {0}", myField); } }; intmain() { // Instantiate the generic interface. IMyGenIface<int>^ myIntObj = gcnew MyIntClass(); // Instantiate the specialized interface "IMySpecializedInt." IMySpecializedInt^ mySpIntObj = (IMySpecializedInt^) myIntObj; // Instantiate the generic interface. IMyGenIface<String^>^ myStringObj = gcnew MyStringClass(); // Instantiate the specialized interface "IMySpecializedString." IMySpecializedString^ mySpStringObj = (IMySpecializedString^) myStringObj; // Call the explicitly implemented interface members. myIntObj->Initialize(1234); mySpIntObj->Display(); myStringObj->Initialize("My string"); mySpStringObj->Display(); }
The integer field contains: 1234 The String field contains: My string