Поскольку вы определили sayIt () как закрытый, класс B не может его переопределить. Таким образом, у вас есть два определения sayIt (), а не одно, которое переопределяется подклассом.
Находясь внутри раздела кода класса A, он всегда будет вызывать версию из класса A, даже если версия класса B была защищенной или общедоступной. Это связано с тем, что класс A знает только о версии из класса A, поскольку версия класса B является , а не переопределением, а совершенно другим методом, который просто имеет одно и то же имя.
Находясь внутри раздела кода класса B, он всегда будет вызывать версию из класса B, поскольку версия класса A помечена как закрытая. Как отметили другие, если вы измените определение на защищенное или общедоступное, оно будет видно классу B и будет делать то, что вы хотите.
Обратите внимание, что если бы вы использовали видимость по умолчанию (пакет), правила области видимости стали бы очень сложными, и фактические результаты варьировались бы в зависимости от того, какие подклассы находятся в одном пакете, а какие - в разных.