How is OOP different in Java, Python and C++?
They differ mostly in how strict they are.
Java Python C++ Multiple inheritance of classes No; many interfaces Yes, by the MRO Yes Access control Enforced Conventions only Enforced, plus friendMethods dynamic by default Yes Yes No, only virtualonesMethod overloading Yes No (last defwins)Yes Cleanup Garbage collector Reference counting plus a cycle collector (CPython) Destructors (RAII) What is
selfin Python?selfis the first parameter of an instance method: the object the method was called on. Python passes it for you, soc.increment()is shorthand forCounter.increment(c).Pythonclass Counter: def __init__(self): self.value = 0 def increment(self): self.value += 1 c = Counter() c.increment() Counter.increment(c) print(c.value)It prints
2.selfis a convention, not a keyword. See Python classes.Can you read a double-underscore attribute from outside a Python class?
Pythonclass Account: def __init__(self): self.__pin = 1234 self._owner = "asha" a = Account() print(hasattr(a, "__pin"), a._owner, a._Account__pin)A name with two leading underscores inside a class is mangled to
_ClassName__name, soself.__pinis stored as_Account__pin.hasattr(a, "__pin")isFalse, whilea._Account__pinstill works. A single underscore is only a convention, and nothing stops access. Mangling avoids name clashes in subclasses; it is not security.Is a list declared in a Python class body per object or per class?
Pythonclass Dog: tricks = [] def __init__(self, name): self.name = name def add_trick(self, trick): self.tricks.append(trick) rex = Dog("Rex") fido = Dog("Fido") rex.add_trick("sit") print(fido.tricks)tricks = []is a class attribute: one list on the class, shared by every instance.self.tricks.append(...)finds that list and mutates it, so Fido sees Rex's trick. Create per-object state in__init__(self.tricks = []); class attributes are safe for constants and values you only read.Which parent's method does Python call on a diamond declared as
D(B, C)?Pythonclass A: def hi(self): return "A" class B(A): def hi(self): return "B" class C(A): def hi(self): return "C" class D(B, C): pass print(D().hi(), [k.__name__ for k in D.__mro__])Python resolves methods along the MRO (method resolution order), computed by C3 linearization: the class, then its parents left to right, with a shared base after every class that inherits from it. For
D(B, C)that isD, B, C, A, object, sohi()comes fromB. More in Python inheritance.Does Python support method overloading?
Not the way Java does. A second
defwith the same name replaces the first, so only the last exists. Use default arguments,*args, orfunctools.singledispatchto choose by the type of the first argument (singledispatchmethod, Python 3.8+, does it for methods).Pythonfrom functools import singledispatch class Calc: def add(self, a, b): return a + b def add(self, a, b, c=0): # replaces the method above return a + b + c print(Calc().add(1, 2), Calc().add(1, 2, 3)) @singledispatch def describe(x): return "something" @describe.register def _(x: int): return f"int {x}" @describe.register def _(x: str): return f"str {x!r}" print(describe(5), describe("hi"), describe(2.5))It prints
3 6, thenint 5 str 'hi' something.What is
@propertyin Python, and why use it instead of getters and setters?@property(a decorator) makes a method read like an attribute, and@name.settervalidates assignments. You can add a property later without changing any caller, so Python code does not writeget_x()andset_x()up front.Pythonclass Temperature: def __init__(self, celsius): self.celsius = celsius # goes through the setter @property def celsius(self): return self._celsius @celsius.setter def celsius(self, value): if value < -273.15: raise ValueError("below absolute zero") self._celsius = value @property def fahrenheit(self): return self._celsius * 9 / 5 + 32 t = Temperature(25) print(t.fahrenheit) try: t.celsius = -300 except ValueError as e: print("Refused:", e)It prints
77.0, thenRefused: below absolute zero.fahrenheithas no setter, so it is read-only.What is duck typing, and how is it different from using interfaces?
Duck typing accepts an object for what it can do, not the type it declares: if it has
speak(), you can callspeak(). Python checks at runtime; Java requiresimplements Speakerand checks at compile time.Pythonclass Duck: def speak(self): return "Quack" class Robot: def speak(self): return "Beep" def chorus(things): return " ".join(t.speak() for t in things) print(chorus([Duck(), Robot()]))It prints
Quack BeepalthoughDuckandRobotshare no parent. A missing method fails only when that line runs.What is a virtual function in C++? What happens without
virtual?A virtual function is dispatched at runtime from the object's actual type when called through a base pointer or reference. Without
virtual, C++ binds the call at compile time from the pointer's type, the opposite of Java's default.#include <iostream> struct Animal { void name() { std::cout << "Animal\n"; } // not virtual virtual void sound() { std::cout << "...\n"; } virtual ~Animal() = default; }; struct Dog : Animal { void name() { std::cout << "Dog\n"; } void sound() override { std::cout << "Woof\n"; } }; int main() { Dog d; Animal& a = d; a.name(); // prints Animal: bound at compile time a.sound(); // prints Woof: dispatched at runtime }A pure virtual function (
= 0) makes the class abstract. See C++ virtual functions.Why does a C++ base class need a virtual destructor?
Deleting a derived object through a base class pointer whose destructor is not
virtualis undefined behavior; usually the derived destructor does not run, so its resources leak.struct Base { ~Base() {} // should be: virtual ~Base() = default; }; struct Buffer : Base { int* data = new int[1000]; ~Buffer() { delete[] data; } }; int main() { Base* p = new Buffer(); delete p; // undefined behavior: ~Buffer() is not called }A base class destructor should be either public and virtual, or protected and non-virtual. See the cppreference delete expression page.
What is the difference between a struct and a class in C++?
The only difference is default access: members and base classes of a
structarepublicby default, those of aclassareprivate. Both can have constructors, methods, inheritance and virtual functions.struct Point { int x, y; }; // x and y are public class Account { int balance; }; // balance is privateBy convention
structholds plain data andclassholds types with invariants.What is a friend function in C++? Does it break encapsulation?
A friend function (or class) is outside code that a class explicitly allows to read its
privateandprotectedmembers. It is not a member and has nothis.#include <iostream> class Money { long paise; public: explicit Money(long p) : paise(p) {} friend std::ostream& operator<<(std::ostream& out, const Money& m); }; std::ostream& operator<<(std::ostream& out, const Money& m) { return out << m.paise / 100 << "." << m.paise % 100 / 10 << m.paise % 10; }The classic use is
operator<<, whose left operand is the stream, so it cannot be a member. Friendship is granted by the class and is neither transitive nor inherited.
OOPs in Java vs Python vs C++
How the same ideas look in Java, Python and C++, with the Python traps as runnable code.