Object Oriented Programming Interview Questions
Object-oriented programming (OOP) concepts serve as the foundational principles for numerous programming languages prevalent in the current landscape. The OOP model has gained immense popularity, leading to its widespread adoption across various programming languages like Java, C++, Python, C#, among others. In light of this significance, we have curated a selection of essential interview questions and answers pertaining to object-oriented programming. These resources are designed to equip you with the knowledge and insights necessary to excel in your interview and demonstrate a comprehensive understanding of OOP concepts.
How much memory does a class occupy?
A class without an object does not require any memory allocation as it exists solely as a blueprint or template. Memory allocation occurs when objects are created, as objects embody the actual implementation of the class's contents. When an object of an empty class is created, the compiler assigns 1 byte for its unique address identification. In the case of multiple objects belonging to the same class, each object can have a distinct memory location assigned to it. The process of creating a new class involves invoking an allocation function, which can have various implementations depending on factors such as the programming language, its version, libraries used, and configuration settings.
What is the meaning of "IS-A" and "HAS-A" relationship?
In OOP, IS-A relationship is completely inheritance. This means, that the child class is a type of parent class. On the other hand, HAS-A relationship is composition. Composition means creating instances which have references to other objects.Foo IS-A Bar:
A HAS-A relationship is dynamic (run time) binding while IS-A relationship is a static (compile time) binding.
What is Dependency?
Dependency refers to a scenario where component Y relies on component X. When component X undergoes modifications, it necessitates corresponding changes in component Y to maintain consistency. A component can manifest in various forms, such as a class, function, interface, method, or even a field. The level of dependency, or coupling, between Y and X can vary, ranging from strong to weak. When one class instantiates another class, it establishes a dependency between the two.
In the scope of Object-Oriented Programming (OOP), inheritance represents a form of strong coupling. Alterations made to a base class are likely to impact its derived classes. Inheritance serves as a mechanism for code reuse; however, it results in dependencies between parent and child classes, deviating from the principle of information hiding and creating a rigid class hierarchy. On the other hand, composition and interface implementation offer a less stringent form of coupling compared to inheritance, while still achieving code reuse objectives.
Can you inherit private members of a class?
In object-oriented programming, a derived class does not inherit direct access to private data members of its base class. However, it does inherit the complete parent object, including any private members declared within the base class. Despite this inheritance, direct access to the private members is restricted as they are exclusively accessible within the base class. Private members are intentionally concealed from external entities, preventing any external class from accessing private member variables or functions. If the intention is to utilize such members in derived classes, accessor functions, such as getter/setter functions, need to be implemented.
In the context of object-oriented programming principles, the purpose of private members is to restrict access to these members by other classes. If a derived class is intended to have access to a member, it should be declared as protected instead of private, indicating a controlled level of accessibility for derived classes.
What are the drawbacks of inheritance?
- Inheritance increases the coupling between base class and derived class. A change in base class will affect all the child classes.
- Inherited functions work slower than normal function as there is indirection.
- Adds extra memory overload for the compiler as it will have to keep records of the parent as well as the child class.
- Often, data members in the base class are left unused which may lead to memory wastage.
- Inheritance relationships generally can't be altered at runtime.
What is the relationship between a class and an object?
A class serves as a fundamental blueprint that facilitates the creation of objects. An object, on the other hand, represents a tangible instance derived from a specific class. The term "instance" signifies the inherent connection between an object and its corresponding class. By defining the methods (behavior) and variables (state), a class outlines the desired characteristics and functionality to be encompassed within instances of that specific object type. Essentially, a class acts as a template, providing the necessary guidelines for constructing objects with consistent behaviors and states.
For example, If CAR is a class, Hyundai, Ford, Suzuki are its objects.
Can you call the base class method without creating an instance?
Yes. Its is possible,
- If it is a static method.
- By inheriting from that class.
- From derived classes using the base keyword.
What is hybrid inheritance?
Hybrid inheritance refers to a type of inheritance in which a class inherits from multiple sources, encompassing various forms and combinations of inheritance. It combines elements of simple inheritance, multiple inheritance, and hierarchical inheritance. In other words, it allows a class to derive characteristics and functionalities from multiple parent classes, resulting in a more versatile and diverse inheritance structure. By using hybrid inheritance, developers can create class hierarchies that incorporate a blend of inheritance types, offering greater flexibility and the ability to model complex relationships and behaviors within their codebase.
What is Polymorphism?
Polymorphism is a fundamental concept in object-oriented programming (OOP) that allows objects of different types to be treated as instances of a common superclass or interface. It enables the same method or property to exhibit different behaviors based on the specific object being referenced at runtime.
There are two main forms of polymorphism:
- Compile-time Polymorphism (Static Polymorphism): This type of polymorphism is achieved through method overloading and operator overloading. Method overloading allows multiple methods with the same name but different parameters to coexist within a class. The appropriate method is chosen based on the arguments provided at compile-time. Operator overloading permits the definition of custom behavior for operators, enabling them to work with user-defined types.
- Runtime Polymorphism (Dynamic Polymorphism): This form of polymorphism is accomplished through method overriding. Method overriding involves defining a method in a subclass that has the same signature (name, return type, and parameters) as a method in its superclass. The overridden method in the subclass is called instead of the superclass's method when invoked on an object of the subclass through a superclass reference or polymorphic reference. This allows different subclasses to provide their own implementation of the same method, enabling specific behaviors for each subclass while maintaining a consistent interface.
Polymorphism facilitates code reusability, modularity, and extensibility. It promotes flexibility by enabling different objects to exhibit specialized behavior while adhering to a common interface. Polymorphic code is more adaptable to changes, as adding new subclasses or modifying existing implementations does not require changes to the code that interacts with the objects via their common superclass or interface.
What are the manipulators in OOP and how it works?
Manipulators are the non-member function specifically designed to be used in conjunction with the insertion (<<) and extraction (>>) operators on stream objects.
They are of two types:
- Manipulators with Arguments (for eg: endl)
- Manipulators without arguments (for eg: stew(), setfill() )
For example, if you want to print the hexadecimal value of 100 then you can print it as:
Difference between Composition and Inheritance?
Composition refers to combining simple types to make more complex ones. An example of Composition in OOPs is where you have an instance of a class within another class, instead of inheriting from it. It simply mean using instance variables that are references to other objects.
- Inheritance is a Parent Child Relationship. A class inherits fields and methods from all its superclasses, whether direct or indirect. A subclass can override methods that it inherits, or it can hide fields or methods that it inherits.
- Composition means HAS-A relationship while Inheritance means IS-A relationship. For example: A car has wheels, an engine, and seats. Car HAS-A Engine (Composition) and Car IS-A Automobile (Inheritance).
What are the levels of data abstraction?
There are three levels of data abstraction:
- Physical (lowest level) : This level describes how data is actually stored in the database.
- Logical (middle level) : This level describes what data is stored in the database.
- View (Highest level) : This level describes the user interaction with the database system.
What is an Inline function?
An inline function refers to a function for which the compiler has been explicitly instructed to perform inline expansion. This instruction serves as a suggestion to the compiler, which retains the discretion to either accept or decline the request. While modern compilers autonomously inline smaller methods based on their optimizations, developers can still manually inline larger methods when desired or deemed beneficial. This flexibility empowers developers to selectively choose which functions should undergo inline expansion, thereby optimizing code execution and potentially improving performance.
What is the difference between new and override?
The "new" modifier serves as an explicit instruction to the compiler, directing it to utilize the implementation of a child class instead of the parent class. This modifier hides the original method, which may or may not be virtual, and enables the provision of distinct functionality. It is crucial to exercise caution and only employ the "new" modifier when it is absolutely necessary, as its usage can lead to potential complexities and hinder code maintainability.
On the other hand, the "override" modifier is specifically applied to virtual methods and is required for abstract methods. By using the "override" modifier, the functionality of a virtual method in a base class can be superseded, allowing for the implementation of alternative behavior. This ensures that the overridden method in the derived class provides unique functionality, tailored to the specific requirements of that class.
The careful utilization of both the "new" and "override" modifiers enables developers to customize and extend the behavior of inherited methods, promoting flexibility and adherence to object-oriented principles.
What is Aggregation?
Aggregation, in object-oriented programming, represents a specialized form of association where two or more objects are interconnected, with each object having its independent life cycle while maintaining an ownership relationship. This association is unidirectional, functioning solely in one direction. Moreover, it signifies a "HAS-A" relationship, indicating that one object possesses or includes another as a component. A significant characteristic of an aggregation relationship is that the parent or whole entity can exist independently without the child or part, and vice versa. This distinction emphasizes the flexibility and autonomy of the involved objects within the aggregation, enabling a modular and loosely coupled design.
What is Inversion of Control?
Inversion of Control (IoC) is a broad term that describes a paradigm shift in which the responsibility for invoking implementations provided by a library, commonly referred to as a toolkit, is transferred from the application to a framework. This pattern is utilized to achieve loose coupling between components and layers within a system. The implementation of IoC is achieved through the practice of dependency injection, where dependencies are supplied to a component during its construction. Typically, these dependencies are defined as interfaces, enhancing decoupling and enabling enhanced testability. Consequently, IoC reconfigures the traditional flow of control in a program. Instead of the callee dictating the control flow, including the creation of dependencies, it is the caller who assumes control, governing the program's overall flow of control.
What is Coupling and Cohesion?
A software system comprises multiple modules, packages, and components, each composed of distinct elements. Coupling pertains to the interaction and interdependence between two modules, packages, or components, whereas cohesion relates to the interaction between elements within a module, package, or component. Coupling reflects the degree of relationship or dependence between these entities, while cohesion signifies the functional capabilities and alignment of the modules, packages, or components.
Reducing coupling between modules, packages, or components ensures that a significant change in one does not have a detrimental impact on others. High coupling hinders code maintenance and modification, as closely interconnected classes may require extensive modifications or system-wide revisions. On the other hand, low cohesion implies a class with a wide range of responsibilities, lacking focus on its intended purpose. In contrast, high cohesion signifies a class that is specifically tailored to its intended functionality, encompassing only methods directly related to its purpose.
In object-oriented programming languages, achieving high cohesion within modules, packages, or components and minimizing coupling between them is often considered indicative of superior code quality and design. Striving for high cohesion promotes a focused and well-defined code structure, while minimizing coupling enhances code modularity, flexibility, and ease of maintenance.
Why use getters and setters/accessors?
The purpose of getters and setters, irrespective of the programming language, is to encapsulate and shield the underlying variable from direct access. This encapsulation enables the addition of verification logic when setting a value, ensuring data integrity. Furthermore, it allows for internal representation changes without impacting external code that relies on the class. Even if immediate verification is not required, the inclusion of getters and setters safeguards against potential future needs.
For instance, consider a birth date field. It may be desirable to restrict the setting of this field to only accept past dates. Without encapsulation, this constraint cannot be enforced if the field is publicly accessible and modifiable. In such cases, the use of getters and setters becomes imperative. As a best practice, member variables are typically made private to prevent direct modification by external programs, promoting encapsulation and preserving the integrity of the class.
What is a copy constructor?
A copy constructor is a member function that initializes an object using another object of the same class. It is used to:
- Initialize one object from another of the same type.
- Copy an object to pass it as an argument to a function.
- Copy an object to return it from a function.
You should write your own copy constructor when there is a pointer type variable inside the class. Compiler will insert copy constructor automatically when there is no explicit copy constructor written inside the code.
Is it always necessary to create objects from class?
No. When a base class method is defined as static, it can be invoked without the need for an object instance. However, if the base class contains non-static methods, an object must be created to access and invoke these methods. In contrast, when a class incorporates static methods, the creation of objects is unnecessary. In such instances, class methods can be directly called using the class name, without the requirement for an object instance. This distinction allows for more flexibility in method invocation, depending on whether the method is static or non-static within the base class.
How is an abstract class different from an interface?
- Interface support multiple implementations while Abstract class does not support multiple inheritance.
- Interface does not contain Constructors and Data Member while Abstract class contains Constructors and Data Member.
- An interface Contains only incomplete member (signature of member) while An abstract class Contains both incomplete (abstract) and complete member.
- Member of interface can not be Static while Complete Member of abstract class can be Static only.
Can you create an instance of an abstract class?
No. You cannot create an instance of an abstract class because it does not have a complete implementation.
What are tokens?
Token is a smallest component in "C" programming language. There are 5 categories of tokens. They are identifiers, constants, strings, keywords and special characters.
What are sealed modifiers?
The "sealed" modifier serves to prohibit the inheritance of a class by other classes. Additionally, it can be applied to a method or property that overrides a virtual method or property in a base class. By employing the "sealed" modifier, you have the ability to permit classes to derive from your class while simultaneously preventing them from overriding specific virtual methods or properties. This feature enhances control and flexibility in class design, enabling selective restriction of method or property overrides to ensure desired behavior and maintain the integrity of the class hierarchy.