Virtual types are simple:
- Classes and traits can have type members. E.g. - trait Foo {
  type T
}
 
- They can be refined (but not overridden once defined): - class Foo1 extends Foo {
  type T <: AnyVal
}
class Foo2 extends Foo1 {
  override type T = Boolean
}
class Foo3 extends Foo2 {
  // override type T = Int // rejected by the compiler – would be unsound
}
 
Here is an example of virtual classes in a Java-descendent language (cclass is a virtual class): 
Features of Virtual Classes 
Let's look
  to another example to study the
  possibilities of virtual classes. We
  will use virtual classes to extend a
  collaboration with a totally new
  funtionality. Let’s say we have a core
  data model to represent expressions:
public cclass ExprModel {
   abstract public cclass Expr {}
   public cclass Constant extends Expr {
      protected int _val;
      public Constant(int val) { 
         _val = val;
      }                 
   }
   abstract public cclass BinaryExpr {
      protected Expr _left;
      protected Expr _right;
      public BinaryExpr(Expr left, Expr right) {
         _left = left;
         _right = right;
      }
   }
   public cclass Add extends BinaryExpr {}
   public cclass Mult extends BinaryExpr {} 
}
The collaboration defines Expr as the
  base class for all expressions,
  concrete classes to represent
  constants, addition and
  multiplication. Class BinaryExpr
  implements the common functionality of
  all expressions with two operands.
  Note that the current version of
  Caesar does not support constructors
  with parameters and abstract methods
  in cclass. The code below demonstrates
  how sample expressions can be built
  using such collaboration:
public model.Expr buildSampleExpr(final ExprModel model) {
   model.Expr const1 = model.new Constant(-3);
   model.Expr const2 = model.new Constant(2);
   model.Expr op1 = model.new Mult(const1, const2);
   model.Expr const3 = model.new Constant(5);
   model.Expr op2 = model.new Add(op1, const3);
   return op2;
}
The collaboration defines Expr as the
  base class for all expressions,
  concrete classes to represent
  constants, addition and
  multiplication. Class BinaryExpr
  implements the common functionality of
  all expressions with two operands.
There are a lot of different
  functionality related with
  expressions: their evaluation,
  formatting expressions to simple text
  in infix or postfix order, various
  consistency checks, lookups and
  transformations. We want to keep all
  this specific functionality separated
  from each other and from the core data
  model. This can be achieved with the
  help of virtual classes. For example,
  the collaboration below extends the
  core model with simple expression
  formatting functionality:
public cclass ExprFormat extends ExprModel {
   abstract public cclass Expr {       
      abstract public void String format();
   }
   public cclass Constant {
      public void String format() { 
         return _val < 0 ? “(“ + _val + “)” : “” + _val; 
      }
   }
   abstract public cclass BinaryExpr {
      public void String format() { 
         return “(” + _left.format() + getOperSymbol() 
                    + _right.format() + “)”; 
      }
      abstract public void String getOperSymbol();
   }
   public cclass Add {
      public void String getOperSymbol() { return “+”; }
   }
   public cclass Mult {
      public void String getOperSymbol() { return “*”; }
   }
}
This short example demonstrates
  various features of virtual classes:
- There is no need to repeat inheritance relationships between
  virtual classes if they are already
  defined in the supercollaboration. For
  example ExprModel defines Constant as
  subclass of Expr. It means that
  Constant is implicitly assumed as
  subclass of Expr in ExprFormat as
  well. 
- Virtual classes can use the fields and methods defined in their
  older versions. For example
  ExprFormat.BinaryExpr can use fields
  _left and _right defined in ExprModel.BinaryExpr. 
- The functionality defined in the overridden virtual classes can be
  accessed without type casts. For
  example, fields _left and _right of
  BinaryExpr were initially declared
  with type Expr of ExprModel, which
  does not have method format(), but in
  the context of ExprFormat the new
  version of Expr is assumed as the type
  of _left and _right. So format() can
  be called without any type casts. 
- The methods introduced in the overridden virtual classes can be
  again overridden in the new versions
  of subclasses. For example overridden
  Expr introduces method format(), which
  can be overridden in BinaryExpr. While
  Add and Mult do not override this
  method further, they inherit the
  format() of BinaryExpr.  
Besides the demonstrated properties,
  the overridden virtual classes can
  also
- introduce new data fields,
- implement new interfaces,
- introduce new inheritance relationships.