Ағылшыншамен салыстырыңыз: абзацты басыңыз — түпнұсқа терезеде ашылады. Абзац астындағы EN түймесі оны мәтін ішінде көрсетеді.
Мазмұны
Кіріспе
Бағдарламалау тілінің түсінігі
Programming language concept
Көптеген бағдарламалау тілдерінің типтік жүйелері субтиптеуді қолдайды. Мысалы, егер тип – түрінің субтипі болса, онда түрінің өрнегі түрінің өрнегі қолданылатын кез келген жерде алмастырылуы тиіс. Варианс – күрделі типтер арасындағы субтиптеу олардың құрауыштары арасындағы субтиптеумен қалай байланысты екенін көрсетеді. Мысалы, s тізімі s тізімімен қалай байланысуы керек? Немесе қайтарым типі – түріндегі функция, қайтарым типі – түріндегі функциямен қалай байланысуы керек? Тип конструкторының вариантына байланысты, қарапайым типтердің субтиптеу қатынасы күрделі типтер үшін сақталуы, кері айналуы немесе ескерілмеуі мүмкін. Мысалы, OCaml бағдарламалау тілінде "Мысық тізімі" "Жануар тізімі" түрінің кіші түрі болып табылады, себебі тізім түрінің конструкторы ковариантты. Бұл қарапайым типтердің субтиптеу қатынасы күрделі типтер үшін сақталады дегенді білдіреді. Екінші жағынан, "Жануардан Стрингке функция" "Мысықтан Стрингке функция" түрінің кіші түрі болып табылады, себебі функция түрінің конструкторы параметр түрі бойынша контравариантты. Мұнда қарапайым типтердің субтиптеу қатынасы күрделі типтер үшін кері айналады. Бағдарламалау тілін жасаушы массивтер, мұрагерлік және жалпы дерек типтері сияқты тіл мүмкіндіктері үшін типтеу ережелерін жасау кезінде вариансты ескереді. Типтік конструкторларды инвариант емес, ковариант немесе контравариант ету арқылы, дұрыс типтелген бағдарламалардың саны артады. Екінші жағынан, бағдарламашылар контравариансты көбінесе түсініксіз деп санайды, ал орындалу кезінде типтік қателерге жол бермеу үшін варианстың дұрыс қадағалануы күрделі типтеу ережелеріне әкелуі мүмкін. Типтік жүйені қарапайым ұстау және пайдалы бағдарламаларға рұқсат беру үшін, тіл типтік конструкторды, оны вариантты деп қарастыру қауіпсіз болса да, инвариант ретінде қарастыруы мүмкін, немесе бұл типтік қауіпсіздікті бұзуы мүмкін болса да, оны ковариант ретінде қарастыруы мүмкін.
Many programming language type systems support subtyping. For instance, if the type is a subtype of , then an expression of type should be substitutable wherever an expression of type is used. Variance is how subtyping between more complex types relates to subtyping between their components. For example, how should a list of s relate to a list of s? Or how should a function that returns relate to a function that returns ? Depending on the variance of the type constructor, the subtyping relation of the simple types may be either preserved, reversed, or ignored for the respective complex types. In the OCaml programming language, for example, "list of Cat" is a subtype of "list of Animal" because the list type constructor is covariant. This means that the subtyping relation of the simple types is preserved for the complex types. On the other hand, "function from Animal to String" is a subtype of "function from Cat to String" because the function type constructor is contravariant in the parameter type. Here, the subtyping relation of the simple types is reversed for the complex types. A programming language designer will consider variance when devising typing rules for language features such as arrays, inheritance, and generic datatypes. By making type constructors covariant or contravariant instead of invariant, more programs will be accepted as well typed. On the other hand, programmers often find contravariance unintuitive, and accurately tracking variance to avoid runtime type errors can lead to complex typing rules. In order to keep the type system simple and allow useful programs, a language may treat a type constructor as invariant even if it would be safe to consider it variant, or treat it as covariant even though that could violate type safety.
Варианс пен мұрагерліктің қысқаша сипаттамасы
Келесі кесте жоғарыда талқыланған тілдерде әдістерді қайта жазу ережелерін жинақтайды. Параметр түрі Қайтару түрі C++ (1998 жылдан бері), Java (J2SE 5.0-ден бері), D, C# (C# 9-дан бері) Тұрақты Ковариант C# (C# 9-дан бұрын) Тұрақты Тұрақты Scala, Sather Контравариант Ковариант Eiffel Ковариант Ковариант
The following table summarizes the rules for overriding methods in the languages discussed above. Parameter type Return type C++ (since 1998), Java (since J2SE 5.0), D, C# (since C# 9) Invariant Covariant C# (before C# 9) Invariant Invariant Scala, Sather Contravariant Covariant Eiffel Covariant Covariant
Жалпы типтері
Жалпыламаларды қолдайтын бағдарламалау тілдерінде (әлде параметрлік полиморфизм деп те аталады), бағдарламашы типтік жүйені жаңа конструкторлармен кеңейте алады. Мысалы, C# интерфейсі сияқты жаңа типтерді құруға мүмкіндік береді, мысалы немесе . Содан кейін осы типтік конструкторлардың дисперсиясы қандай болуы керек деген сұрақ туындайды. Екі негізгі тәсіл бар. Декларация орнында дисперсияны көрсету мүмкіндігі бар тілдерде (мысалы, C#), бағдарламашы жалпы типтің анықтамасын оның типтік параметрлерінің күтілетін дисперсиясымен бірге көрсетеді. Пайдалану орнында дисперсияны көрсету мүмкіндігі бар тілдерде (мысалы, Java), бағдарламашы жалпы типті инстанцияланған жерлерді көрсетеді.
In programming languages that support generics (a. k. a. parametric polymorphism), the programmer can extend the type system with new constructors. For example, a C# interface like makes it possible to construct new types like or The question then arises what the variance of these type constructors should be. There are two main approaches. In languages with declaration site variance annotations (e. g., C#), the programmer annotates the definition of a generic type with the intended variance of its type parameters. With use site variance annotations (e. g., Java), the programmer instead annotates the places where a generic type is instantiated.
Декларация-сайты бойынша ауытқулар туралы түсініктемелер
Декларация орнындағы вариациялық белгілемелермен ең көп қолданылатын тілдер – C# және Kotlin ( және кілт сөздерін пайдаланып), Scala және OCaml ( және кілт сөздерін пайдаланып). C# тек интерфейс түрлері үшін ғана вариациялық белгілемелерге рұқсат береді, ал Kotlin, Scala және OCaml оларды интерфейс түрлері мен нақты дерек түрлері үшін де қолдануға мүмкіндік береді.
The most popular languages with declaration site variance annotations are C# and Kotlin (using the keywords and ), and Scala and OCaml (using the keywords and ). C# only allows variance annotations for interface types, while Kotlin, Scala and OCaml allow them for both interface types and concrete data types.
Этимология
Бұл терминдер категориялар теориясындағы ковариантты және контравариантты функторлар ұғымынан туындайды. Объектілері типтер, ал морфизмдері ≤ кіші тип қатынасын көрсететін санатты қарастырайық. (Бұл кез келген ішінара реттелген жиынның категория ретінде қарастырылуының мысалы.) Содан кейін, мысалы, функция түрінің конструкторы екі типті – p және r – қабылдап, жаңа p → r типін жасайды; демек, ол нысандарды нысандарға түрлендіреді. Функция типтері үшін кіші типтеу ережесіне сәйкес, бұл операция бірінші параметр үшін ≤ белгісін керітеді, ал екіншісі үшін сақтайды, сондықтан ол бірінші параметрде контравариантты функтор, ал екіншісінде ковариантты функтор болып табылады.
These terms come from the notion of covariant and contravariant functors in category theory. Consider the category whose objects are types and whose morphisms represent the subtype relationship ≤. (This is an example of how any partially ordered set can be considered as a category.) Then for example the function type constructor takes two types p and r and creates a new type p → r; so it takes objects in to objects in By the subtyping rule for function types this operation reverses ≤ for the first parameter and preserves it for the second, so it is a contravariant functor in the first parameter and a covariant functor in the second.