When a Variable or VariableType is defined, the DataType of the Value is defined by the DataType, ValueRank and ArrayDimensions Attributes. In general, it is always allowed for the Value to use a subtype of the DataType unless restricted in the NoSubDataTypes bit of the AccessLevelEx Attribute. In fields of a structure, using subtypes is allowed when IsOptional is set and it is a StructureWithOptionalFields or the DataType is an abstract DataType like the BaseDataType. In many cases where it is allowed to use subtypes, not all possible subtypes are allowed, but the DataType hierarchy does not allow to restrict this by one supertype. For example, when an Int16 and Int32 are allowed, their common supertype Integer would also allow SByte and Int64.
A SubtypeRestriction limits the usage of subtypes to a subset of all subtypes of a DataType. It is represented by an Object of SubtypeRestrictionType defined in OPC 10000-5. A SubtypeRestriction Object is bound to a DataType by a HasDataTypeRefinement Reference from the DataType to the SubtypeRestriction Object. Each SubtypeRestriction Object shall be referenced from exactly one DataType Node using a HasDataTypeRefinement Reference. A SubtypeRestriction Object is referencing Variables with an AllowedSubtype Reference (see 7.29), and thereby restricting that the DataType including ValueRank and ArrayDimensions of the Variable is allowed to be used as subtype. The general rules of inheritance defined in 6.3 apply, i.e., the DataType shall be the same or a subtype of the DataType, the ValueRank can only be changed according to the subtyping rules, etc.
A SubtypeRestriction Object should have at least two AllowedSubtype References to Variables defining different variations of subtypes. Otherwise, a Variable using the SubtypeRestriction should just use the concrete subtype and does not need a SubtypeRestriction.
In Figure 23, an example of a SubtypeRestriction Object is given. The Y:Restriction1 Object is referenced from Number and therefore can be used by any Variable using the Number DataType. It references two Variables, Y:UInt32 with the DataType UInt32, the ValueRank Scalar which does not allow subtypes and X:IntegerArray, of Integer, ValueRank OneDimension that does allow subtypes (which is required since Integer is an abstract DataType). Thereby, any Variable using the SubtypeRestriction is limiting its values to scalar UInt32s or arrays of Integer or any subtypes of Integer.
Figure 23 – Example of a SubtypeRestriction
In the example, Z:SampleVar is using the Y:Restriction1 by referencing it with UsesSubtypeRestriction. This is allowed since the DataType of Z:SampleVar is Number. The DataTypes always have to match exactly. The NoSubDataTypes is set to true, which is required, since Number is abstract, but would also be required for a concrete DataType, since setting it to true is already restricting it to disallow subtypes.
In order to use a SubtypeRestriction, the ValueRank and ArrayDimensions Attribute of the Variable using the SubtypeRestriction shall be compatible to all referenced Variables using AllowedSubtype, i.e., it is required that based on the definitions of the Variable using the SubtypeRestriction a value based on any of the referenced Variables can be used.
A SubtypeRestriction shall only be used on Variables used as instances, never on InstanceDeclarations or VariableTypes.
For Method Arguments, it can be used in combination with the HasArgumentDescription.