OOPS Problems

 


Example 1: Method Overloading vs. Method Overriding

public class BaseClass
{
    public virtual string Display()
    {
        return "BaseClass Display";
    }

    public string Display(int number)
    {
        return "BaseClass Display with number: " + number;
    }
}

public class DerivedClass : BaseClass
{
    public override string Display()
    {
        return "DerivedClass Display";
    }
}

class Program
{
    static void Main()
    {
        BaseClass obj = new DerivedClass();
        Console.WriteLine(obj.Display());          // Output: "DerivedClass Display"
        Console.WriteLine(obj.Display(10));        // Output: "BaseClass Display with number: 10"
    }
}
  • Concepts:
    • Method Overloading: The Display(int number) method in BaseClass shows overloading (same method name but different parameters).
    • Method Overriding: DerivedClass overrides Display() to change the implementation.

Example 2: Interface vs. Abstract Class

public interface IShape
{
    double Area();
}

public abstract class Shape
{
    public abstract double Area();
    public void Display()
    {
        Console.WriteLine("Shape Display");
    }
}

public class Circle : Shape, IShape
{
    private double radius;
    public Circle(double r)
    {
        radius = r;
    }

    public override double Area()
    {
        return Math.PI * radius * radius;
    }
}

class Program
{
    static void Main()
    {
        Circle c = new Circle(5);
        Console.WriteLine("Area: " + c.Area());  // Output: Area: 78.5398163397448
        c.Display();                             // Output: Shape Display
    }
}
  • Concepts:
    • Abstract Class: Shape provides a common implementation (e.g., Display()), while forcing subclasses to implement Area().
    • Interface: IShape only declares Area() without any implementation, allowing multiple inheritance.

Example 3: Method Hiding with new Keyword

public class Animal
{
    public void Speak()
    {
        Console.WriteLine("Animal speaks");
    }
}

public class Dog : Animal
{
    public new void Speak()
    {
        Console.WriteLine("Dog barks");
    }
}

class Program
{
    static void Main()
    {
        Animal myAnimal = new Dog();
        myAnimal.Speak();  // Output: "Animal speaks"
    }
}
  • Concepts:
    • Method Hiding: Dog hides Animal's Speak() method using the new keyword.
    • The method invoked depends on the reference type (Animal in this case), not the actual object type (Dog).

Example 4: Polymorphism with Interfaces

public interface IVehicle
{
    void Drive();
}

public class Car : IVehicle
{
    public void Drive()
    {
        Console.WriteLine("Car is driving");
    }
}

public class Truck : IVehicle
{
    public void Drive()
    {
        Console.WriteLine("Truck is driving");
    }
}

class Program
{
    static void Main()
    {
        IVehicle myVehicle = new Car();
        myVehicle.Drive();  // Output: "Car is driving"

        myVehicle = new Truck();
        myVehicle.Drive();  // Output: "Truck is driving"
    }
}
  • Concepts:
    • Polymorphism: The same interface (IVehicle) is used to refer to different types of vehicles (CarTruck), but the Drive() method behaves according to the actual object type.

Example 5: Abstract Class and Method Overriding

public abstract class Employee
{
    public abstract void Work();
    public void GetDetails()
    {
        Console.WriteLine("Employee details");
    }
}

public class Manager : Employee
{
    public override void Work()
    {
        Console.WriteLine("Manager works");
    }
}

public class Developer : Employee
{
    public override void Work()
    {
        Console.WriteLine("Developer works");
    }
}

class Program
{
    static void Main()
    {
        Employee emp = new Manager();
        emp.Work();            // Output: "Manager works"
        emp.GetDetails();      // Output: "Employee details"

        emp = new Developer();
        emp.Work();            // Output: "Developer works"
    }
}
  • Concepts:
    • Abstract Class: Employee forces derived classes (ManagerDeveloper) to implement the Work() method.
    • Method Overriding: Different implementations of Work() in Manager and Developer.

Example 6: Multiple Interfaces

public interface IPrintable
{
    void Print();
}

public interface IScannable
{
    void Scan();
}

public class MultiFunctionPrinter : IPrintable, IScannable
{
    public void Print()
    {
        Console.WriteLine("Printing document");
    }

    public void Scan()
    {
        Console.WriteLine("Scanning document");
    }
}

class Program
{
    static void Main()
    {
        MultiFunctionPrinter mfp = new MultiFunctionPrinter();
        mfp.Print();  // Output: "Printing document"
        mfp.Scan();   // Output: "Scanning document"
    }
}
  • Concepts:
    • Multiple Interface Implementation: MultiFunctionPrinter implements both IPrintable and IScannable, demonstrating the ability to fulfill multiple contracts.

 


Name Hiding

public class A
{
    public int Add(int a, int b)
    {
        return a + b;
    }
}


public class B : A
{
    public float Add(int a, int b) // name hiding
    {
        return a + b;
    }
}

Class Definitions

  1. classA
public class classA
{
    public virtual string Print() { return "classA"; }
}
  • classA declares a virtual method Print() that returns "classA". The virtual keyword allows this method to be overridden in derived classes.

  • classB : classA

public class classB : classA
{
    public override string Print() { return "classB"; }
}
  • classB inherits from classA. It overrides the Print() method with its own implementation that returns "classB". The override keyword indicates that it is overriding the base class (classA) method.

  • classC : classB

public class classC : classB
{
    public new string Print() { return "ClassC"; }
}
  • classC inherits from classB. It introduces a new method Print() using the new keyword. This means classC has its own implementation of Print() that hides (but does not override) the Print() method from classB.

Usage Example

classA a = new classC();
Console.WriteLine(a.Print()); // Output: "classB"
  • Here, an instance of classC is created and assigned to a variable of type classA.
  • Despite the variable a being declared as classA, it actually points to an instance of classC.
  • When a.Print() is called, the method that is invoked depends on the actual type of the object (classC in this case), not the declared type of the variable (classA).
  • Therefore, a.Print() calls the overridden method Print() in classB (since classC inherits from classB), which returns "classB".

Explanation

  • InheritanceclassC inherits from classB, which in turn inherits from classA. This forms a hierarchy (classA -> classB -> classC).
  • Method OverridingclassB overrides the Print() method from classAclassC does not override Print(); instead, it introduces a new method with the same name (Print()) using new.
  • Method Hiding: The new keyword in classC's Print() method indicates that it hides the Print() method of classB and does not participate in polymorphism. Hence, when a.Print() is called, the method from classB ("classB") is invoked, not the one from classC.

This behavior is why the output of Console.WriteLine(a.Print()); is "classB" instead of "ClassC".




Class and Interface Definitions

  1. Interface IA
public interface IA
{
    string Print();
}
  • IA is an interface with a single method Print(). Any class that implements this interface must provide an implementation for this method.

  • Class classA

public class classA : IA
{
    public virtual string Print() { return "classA"; }
}
  • classA implements the IA interface by providing a Print() method.
  • The Print() method is marked as virtual, meaning it can be overridden in derived classes.

  • Class classB

public class classB : classA
{
    public override string Print() { return "classB"; }
}
  • classB inherits from classA and overrides the Print() method, changing the return value to "classB".

  • Class classC

public class classC : classB
{
    public new string Print() { return "ClassC"; }
}
  • classC inherits from classB and introduces a new Print() method using the new keyword. This new method hides the overridden Print() method in classB but does not override it.

Class TakeAction

public class TakeAction
{
    public void PrintName(IA obj)
    {
        Console.WriteLine(obj.Print());
    }
}
  • The TakeAction class has a method PrintName that accepts an object implementing the IA interface.
  • Inside the PrintName method, it calls obj.Print() and prints the result to the console.

Main Code Execution

var obj = new TakeAction();
classA a = new classC();
obj.PrintName(a);
  • An instance of TakeAction is created.
  • A variable a of type classA is assigned an instance of classC.
  • When obj.PrintName(a) is called:
    • Since a is of type classA but references an instance of classC, the actual method that gets called depends on the inheritance chain and method overrides.
    • PrintName(a) expects an object of type IA, which classA implements.
    • The Print() method in classB is the one that gets called because classC only hides the Print() method with new, but it doesn't override it.
    • The Print() method in classB is an override of classA's Print() method, so it returns "classB".

Output

  • The output of Console.WriteLine(obj.PrintName(a)); will be "classB".

Key Concepts

  • InheritanceclassC inherits from classB, which inherits from classA.
  • Method OverridingclassB overrides Print() from classA.
  • Method HidingclassC introduces a new Print() method that hides classB's Print() method but does not override it.
  • Interface ImplementationclassA implements the IA interface, which ensures that Print() is a valid method for IA type.

When PrintName(a) is called, the runtime checks the actual type of a (which is classC) and walks up the inheritance chain to find the appropriate Print() method to call. Since classC hides but does not override the Print() method, the overridden method in classB is invoked, resulting in the output "classB".



Post a Comment

Contact Form