In the client, one can have case A (old solution): double b = account.getBalance(); or case B (your new suggestion): MoneyType b = account.getBalance(); . In case A, the client's author can then write ::std:cout << 0.05 * b; . In case B, the client needs more support from the implementation to be able to do this. The client's author is not supposed to know that »MoneyType« is just »double«. Therefore, he cannot write: ::std:cout << 0.05 * b; , because he does not know whether MoneyType supports those operations and what their semantics is. But usually the client might need to calculated something with the balance or to serialize it to a human-readable stream. So he needs more support from the library than just the statement »MoneyType is an opaque type that you do not need to know anything about.« Possibly, MoneyType might grow to become a new type implemented by a class. Well, then this class better not have a »toDouble()« method, because otherwise the clients might use it and then the same problem will arise anew.