@@ -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 >`
@@ -134,8 +135,10 @@ The body of a class can contain:
134
135
- Any number of :ref: `field <fields >` declarations.
135
136
136
137
When 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.
139
142
140
143
.. _characteristic-predicates :
141
144
@@ -242,6 +245,7 @@ A class :ref:`annotated <abstract>` with ``abstract``, known as an **abstract**
242
245
the values in a larger type. However, an abstract class is defined as the union of its
243
246
subclasses. In particular, for a value to be in an abstract class, it must satisfy the
244
247
characteristic predicate of the class itself **and ** the characteristic predicate of a subclass.
248
+ Note that final extensions are not considered subclasses in this context.
245
249
246
250
An abstract class is useful if you want to group multiple existing classes together
247
251
under 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.
281
285
Overriding member predicates
282
286
============================
283
287
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 >`.
287
291
This is useful if you want to refine the predicate to give a more specific result for the
288
292
values in the subclass.
289
293
@@ -382,6 +386,68 @@ from ``OneTwoThree`` and ``int``.
382
386
must :ref: `override <overriding-member-predicates >` those definitions to avoid ambiguity.
383
387
:ref: `Super expressions <super >` are often useful in this situation.
384
388
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
+
385
451
.. _instanceof-extensions :
386
452
387
453
Non-extending subtypes
0 commit comments