@@ -112,12 +112,13 @@ the supertypes (that is, they are in the :ref:`class domain type <domain-types>`
112
112
A class inherits all member predicates from its base types.
113
113
114
114
A 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 `."
115
116
Classes can also specialise other types without extending the class interface via `instanceof `,
116
117
see ":ref: `instanceof-extensions `.".
117
118
118
119
To be valid, a class:
119
120
- 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.
121
122
- Must not extend types that are incompatible. For more information, see ":ref: `type-compatibility `."
122
123
123
124
You 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**
242
243
the values in a larger type. However, an abstract class is defined as the union of its
243
244
subclasses. In particular, for a value to be in an abstract class, it must satisfy the
244
245
characteristic predicate of the class itself **and ** the characteristic predicate of a subclass.
246
+ Note that final extensions are not considered subclasses in this context.
245
247
246
248
An abstract class is useful if you want to group multiple existing classes together
247
249
under 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.
281
283
Overriding member predicates
282
284
============================
283
285
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 >`.
287
289
This is useful if you want to refine the predicate to give a more specific result for the
288
290
values in the subclass.
289
291
@@ -382,6 +384,68 @@ from ``OneTwoThree`` and ``int``.
382
384
must :ref: `override <overriding-member-predicates >` those definitions to avoid ambiguity.
383
385
:ref: `Super expressions <super >` are often useful in this situation.
384
386
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
+
385
449
.. _instanceof-extensions :
386
450
387
451
Non-extending subtypes
0 commit comments