complicated class hierarchy