Constraining types

Type constraint methods

Note

The examples below use the Java QL library. All QL libraries support using these methods to constrain variables, the only difference is in the names of the classes used.

There are several ways of imposing type constraints on variables:

  • Use an instanceof test, for example:

    import java
    
    from Type t
    where t instanceof Class
    select t
    
  • Use a cast, for example:

    import java
    
    from Type t
    where t.(Class).getASupertype().hasName("List")
    select t
    
  • Set the variable equal to another variable with the required type using exists, for example:

    import java
    
    from Type t
    where exists(Class c |
        c = t
        and c.getASupertype().hasName("List")
    )
    select t
    
  • Pass the variable to a predicate that expects a variable of the required type, for example:

    import java
    
    predicate derivedFromList(Class c) {
        c.getASupertype().hasName("List")
    }
    
    from Type t
    where derivedFromList(t)
    select t
    

All of these methods constrain the variable t to have values of type Class.

Choosing between the methods

These methods have advantages and disadvantages depending on the extent to which you need to work with the variable as the new type:

  • instanceof only checks that the variable has the required type.
  • A cast gives you one, and only one, access to the variable as the new type.
  • Creating a new variable with exists or a predicate parameter allows repeated access to the variable as the new type.
    • Note that due to the ability to overload predicates in a class, predicates that belong to a class must be supplied with arguments of the exact type they specify, and so this technique will not work in that situation.