@@ -112,12 +112,13 @@ the supertypes (that is, they are in the :ref:`class domain type <domain-types>`
112112A class inherits all member predicates from its base types.
113113
114114A class can extend multiple types. For more information, see ":ref: `multiple-inheritance `."
115+ A class can extend final types (or final aliases of types), see ":ref: `final-extensions `."
115116Classes can also specialise other types without extending the class interface via `instanceof `,
116117see ":ref: `instanceof-extensions `.".
117118
118119To be valid, a class:
119120 - Must not extend itself.
120- - Must not extend a :ref: ` final ` class.
121+ - Must not (transitively) extend a non- final type and a final alias of that same type.
121122 - Must not extend types that are incompatible. For more information, see ":ref: `type-compatibility `."
122123
123124You can also annotate a class. See the list of :ref: `annotations <annotations-overview >`
@@ -134,8 +135,10 @@ The body of a class can contain:
134135 - Any number of :ref: `field <fields >` declarations.
135136
136137When you define a class, that class also inherits all non-:ref: `private ` member predicates and
137- fields from its supertypes. You can :ref: `override <overriding-member-predicates >` those
138- predicates and fields to give them a more specific definition.
138+ fields from its supertypes.
139+
140+ Depending on whether they are final, you can :ref: `override <overriding-member-predicates >` or
141+ :ref: `shadow <final-extensions >` those predicates and fields to give them a more specific definition.
139142
140143.. _characteristic-predicates :
141144
@@ -242,6 +245,7 @@ A class :ref:`annotated <abstract>` with ``abstract``, known as an **abstract**
242245the values in a larger type. However, an abstract class is defined as the union of its
243246subclasses. In particular, for a value to be in an abstract class, it must satisfy the
244247characteristic predicate of the class itself **and ** the characteristic predicate of a subclass.
248+ Note that final extensions are not considered subclasses in this context.
245249
246250An abstract class is useful if you want to group multiple existing classes together
247251under a common name. You can then define member predicates on all those classes. You can also
@@ -281,9 +285,9 @@ there is no need to update the queries that rely on it.
281285Overriding member predicates
282286============================
283287
284- If a class inherits a member predicate from a supertype, you can **override ** the inherited
285- definition. You do this by defining a member predicate with the same name and arity as the
286- inherited predicate, and by adding the ``override `` :ref: `annotation <override >`.
288+ If a class inherits a member predicate from a non-final supertype, you can **override ** the
289+ inherited definition. You do this by defining a member predicate with the same name and arity
290+ as the inherited predicate, and by adding the ``override `` :ref: `annotation <override >`.
287291This is useful if you want to refine the predicate to give a more specific result for the
288292values in the subclass.
289293
@@ -382,6 +386,68 @@ from ``OneTwoThree`` and ``int``.
382386 must :ref: `override <overriding-member-predicates >` those definitions to avoid ambiguity.
383387 :ref: `Super expressions <super >` are often useful in this situation.
384388
389+ .. _final-extensions :
390+
391+ Final extensions
392+ ================
393+
394+ A class can extend final types or final aliases of types. In that case, it inherits final
395+ versions of all the member predicates and fields of those supertypes.
396+ Member predicates that are inherited through final extensions cannot be overridden,
397+ but they can be shadowed.
398+
399+ For example, extending the class from the :ref: `first example <defining-a-class >`:
400+
401+ .. code-block :: ql
402+
403+ final class FinalOneTwoThree = OneTwoThree;
404+
405+ class OneTwoFinalExtension extends FinalOneTwoThree {
406+ OneTwoFinalExtension() {
407+ this = 1 or this = 2
408+ }
409+
410+ string getAString() {
411+ result = "One or two: " + this.toString()
412+ }
413+ }
414+
415+ The member predicate ``getAString() `` shadows the original definition of ``getAString() ``
416+ from ``OneTwoThree ``.
417+
418+ Different to overriding (see ":ref: `overriding-member-predicates `"),
419+ final extensions leave the extended type unchanged:
420+
421+ .. code-block :: ql
422+
423+ from OneTwoTree o
424+ select o, o.getAString()
425+
426+ +---+-------------------------+
427+ | o | ``getAString() `` result |
428+ +===+=========================+
429+ | 1 | One, two or three: 1 |
430+ +---+-------------------------+
431+ | 2 | One, two or three: 2 |
432+ +---+-------------------------+
433+ | 3 | One, two or three: 3 |
434+ +---+-------------------------+
435+
436+ However, when calling ``getAString() `` on ``OneTwoFinalExtension ``, the original definition is shadowed:
437+
438+ .. code-block :: ql
439+
440+ from OneTwoFinalExtension o
441+ select o, o.getAString()
442+
443+ +---+-------------------------+
444+ | o | ``getAString() `` result |
445+ +===+=========================+
446+ | 1 | One or two: 1 |
447+ +---+-------------------------+
448+ | 2 | One or two: 2 |
449+ +---+-------------------------+
450+
385451.. _instanceof-extensions :
386452
387453Non-extending subtypes
0 commit comments