Extend the static semantics of typed KOOL with private members.  See
also the exercise "private-members" of the dynamic semantics of typed
KOOL, because our objective here is to type precisely all the correct
programs of that exercise (in addition to the programs of the original
typed KOOL).

Recall that the role of a static semantics, or type checker, is to
reject programs which may yield runtime errors ("may", because type
checkers typically also reject programs which would otherwise execute
correctly with the dynamic semantics).  There are two runtime problems
that the addition of private members generate:

1) A method from a subclass accesses a private member of a superclass.
In this case, a runtime error is generated by the dynamically typed
KOOL, so want our type checker to reject such programs.  To do it,
like in Java we consevatively reject those programs in which a method
statically accesses a private member of a superclass.  This is
conservative because it may very well be the case in dynamically typed
KOOL that the superclass access may be a method call which is
dynamically dispatched to a subsequent subclass that publicly
overrides the private method.  We will therefore reject such otherwise
correct programs.

2) A method accesses a private method of a subclass.  This could
happen when, for example, class A contains public methods f and g,
and class B extends A and overrides f with a private method.  Now if
we call g on an instance of B in dynamically typed KOOL, we get a
runtime error due to dynamic dispatch (g accesses a private member of
another class).  So we want our type checker to reject such programs,
too.  To do it, like in Java we conservatively reject the programs in
which a class overrides a public method of a superclass with a private
method.
