/**
   * Return an expression that allows you to treat its base as if it were a subclass of the class
   * returned by the base This can only be called on an ExpressionBuilder, the result of
   * expression.get(String), expression.getAllowingNull(String), the result of
   * expression.anyOf("String") or the result of expression.anyOfAllowingNull("String")
   *
   * <p>downcast uses Expression.type() internally to guarantee the results are of the specified
   * class.
   *
   * <p>Example:
   *
   * <pre><blockquote>
   *     Expression: employee.get("project").as(LargeProject.class).get("budget").equal(1000)
   *     Java: ((LargeProject)employee.getProjects().get(0)).getBudget() == 1000
   *     SQL: LPROJ.PROJ_ID (+)= PROJ.PROJ_ID AND L_PROJ.BUDGET = 1000 AND PROJ.TYPE = "L"
   * </blockquote></pre>
   */
  @Override
  public Expression treat(Class castClass) {
    // to be used on expressionBuilders
    QueryKeyExpression clonedExpression = new TreatAsExpression(castClass, this);
    clonedExpression.shouldQueryToManyRelationship = false;
    clonedExpression.hasQueryKey = false;
    clonedExpression.hasMapping = false;

    this.addDerivedExpression(clonedExpression);
    return clonedExpression;
  }
 /**
  * INTERNAL: Return if the expression is equal to the other. This is used to allow dynamic
  * expression's SQL to be cached.
  */
 public boolean equals(Object object) {
   if (this == object) {
     return true;
   }
   if (!super.equals(object)) {
     return false;
   }
   QueryKeyExpression expression = (QueryKeyExpression) object;
   // Return false for anyOf expressions, as equality is unknown.
   if (shouldQueryToManyRelationship() || expression.shouldQueryToManyRelationship()) {
     return false;
   }
   return ((getName() == expression.getName())
       || ((getName() != null) && getName().equals(expression.getName())));
 }