Вы изменяете подпись метода foo способом, который не поддерживается. Полиморфизм работает только для другого списка аргументов, а не для идентичных методов, отличающихся только типом возвращаемого значения.
И если вы подумаете об этом, это вполне естественно ... Если бы это сработало, и кто-то, кто знает только об одном из двух суперклассов, вызвал бы Three.foo (), он ожидал, что он вернет единицу (потому что это то, как это работает в One и Two), но в Three вы можете на самом деле вернуть HashMap и при этом вести себя правильно.
Джон (в комментарии ниже) является правильным, вы можете сузить область, но тогда вы все равно будете следовать протоколу, что вы вернете «One» (если вы вернете Three из Three.foo ()), потому что подклассы будут все реализуют интерфейс суперкласса.
Однако тип возвращаемого значения по-прежнему не является частью полиморфизма, поэтому у вас не может быть трех разных методов, которые отличаются только типом возвращаемого значения.