There are two classes

public class CardAction { public void doPayment(double amountPayment) { System.out.println("complete from debt card"); } } public class CreditCardAction extends CardAction { public boolean checkCreditLimit() { return true; } @Override public void doPayment(double amountPayment) { System.out.println("complete from credit card"); } } 

Why, with such an object creation, is there only access to the overridden methods in the subclass, and no new (non-polymorphic) access methods?

 CardAction dc2 = new CreditCardAction(); 
  • Ptmcht is the essence of polymorphism?) - Alexey Shimansky
  • one
    ru.stackoverflow.com/questions/491263/… ...... answer times ....... ru.stackoverflow.com/questions/279518/… ..... answer two ...... etc. .... maybe even in a search, look?)) - Alexey Shimansky
  • 2
    because you have a class variable CardAction , and in the class CardAction there is only a doPayment method, it would be strange if some other method suddenly appeared in it - Grundy
  • Write an example of a new method - Senior Pomidor
  • @ TsovakSaakyan, so in the example there is already a checkCreditLimit - Grundy

2 answers 2

Because their (non-polymorphic methods) may not be

... and therefore it is not safe (with type safety)

By assigning a value to a variable of a base type for it (i.e. an up-cast , which generalizes caste, conversion to a supertype / base type), you limit your ability to work with it only on what is in the base type . At the language level, you lose information about what type the source value was (at runtime it still has, but more on that later), you have a base type value. What is really inside of it, you should not be interested in it.

Instead, you get the opportunity to work with the value of any suitable type, even one that you may not even be aware of at the time of development. For example, for your library, the user can implement their own class and pass its objects to your code. Without your participation in its product.

This applies not only to classes and their base (by inheritance) classes, but also to classes and the interfaces they implement . Interfaces are also types, although they do not exist at all in their pure form, but they determine the common features of all types suitable for them: therefore, it is safe to use the value of an interface type only with these very common features .

It makes sense if you remember what errors the typing is checking for the compiler to avoid: basically these are errors of getting a value in some place that does not have some of the capabilities required there. Capability determines the type of variable . The compiler tries to prove that these possibilities exist, and if it cannot, it tells you how to place a potential error.


Specifically, in Java there is a down-casting, a conversion from a more general type to a more specific one, but only explicit , which already hints that this action is dangerous and can end in an error ( ClassCastException ).

But this is not everywhere and they should be used only in extreme cases.

  • In practice, this announcement is used? CardAction dc2 = new CreditCardAction (); - jisecayeyo
  • @jisecayeyo I don’t see much point in this, because wherever you work with a more general type, you can specify it and when you transfer an object to a particular type, implicit upcast will occur to the desired type. But I met such code. This could be the result of refactoring with type replacement, for example. - D-side

You create an object of class CardAction that does not have a checkCreditLimit() method. To call this method, you must create an object of the CreditCardAction class CreditCardAction

 CreditCardAction dc2 = new CreditCardAction(); dc2.checkCreditLimit(); 
  • 2
    creates a vehicle just CreditCardAction , and assigns it to a variable of the base type CardAction — Igor