@@ -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 >`
@@ -242,6 +243,7 @@ A class :ref:`annotated <abstract>` with ``abstract``, known as an **abstract**
242243the values in a larger type. However, an abstract class is defined as the union of its
243244subclasses. In particular, for a value to be in an abstract class, it must satisfy the
244245characteristic predicate of the class itself **and ** the characteristic predicate of a subclass.
246+ Note that final extensions are not considered subclasses in this context.
245247
246248An abstract class is useful if you want to group multiple existing classes together
247249under a common name. You can then define member predicates on all those classes. You can also
@@ -281,9 +283,9 @@ there is no need to update the queries that rely on it.
281283Overriding member predicates
282284============================
283285
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 >`.
286+ If a class inherits a member predicate from a non-final supertype, you can **override ** the
287+ inherited definition. You do this by defining a member predicate with the same name and arity
288+ as the inherited predicate, and by adding the ``override `` :ref: `annotation <override >`.
287289This is useful if you want to refine the predicate to give a more specific result for the
288290values in the subclass.
289291
@@ -382,6 +384,68 @@ from ``OneTwoThree`` and ``int``.
382384 must :ref: `override <overriding-member-predicates >` those definitions to avoid ambiguity.
383385 :ref: `Super expressions <super >` are often useful in this situation.
384386
387+ .. _final-extensions :
388+
389+ Final extensions
390+ ================
391+
392+ A class can extend final types or final aliases of types. In that case, it inherits final
393+ versions of all the member predicates and fields of those supertypes.
394+ Member predicates that are inherited through final extensions cannot be overridden,
395+ but they can be shadowed.
396+
397+ For example, extending the class from the :ref: `first example <defining-a-class >`:
398+
399+ .. code-block :: ql
400+
401+ final class FinalOneTwoThree = OneTwoThree;
402+
403+ class OneTwo extends FinalOneTwoThree {
404+ OneTwo() {
405+ this = 1 or this = 2
406+ }
407+
408+ string getAString() {
409+ result = "One or two: " + this.toString()
410+ }
411+ }
412+
413+ The member predicate ``getAString() `` shadows the original definition of ``getAString() ``
414+ from ``OneTwoThree ``.
415+
416+ Different to overriding (see ":ref: `overriding-member-predicates `"),
417+ final extensions leave the extended type unchanged:
418+
419+ .. code-block :: ql
420+
421+ from OneTwoTree o
422+ select o, o.getAString()
423+
424+ +---+-------------------------+
425+ | o | ``getAString() `` result |
426+ +===+=========================+
427+ | 1 | One, two or three: 1 |
428+ +---+-------------------------+
429+ | 2 | One, two or three: 2 |
430+ +---+-------------------------+
431+ | 3 | One, two or three: 3 |
432+ +---+-------------------------+
433+
434+ However, when calling ``getAString() `` on ``OneTwo ``, the original definition is shadowed:
435+
436+ .. code-block :: ql
437+
438+ from OneTwo o
439+ select o, o.getAString()
440+
441+ +---+-------------------------+
442+ | o | ``getAString() `` result |
443+ +===+=========================+
444+ | 1 | One or two: 1 |
445+ +---+-------------------------+
446+ | 2 | One or two: 2 |
447+ +---+-------------------------+
448+
385449.. _instanceof-extensions :
386450
387451Non-extending subtypes
0 commit comments