C# ఇన్హెరిటెన్స్, పాలిమార్ఫిజం (virtual, override, new, sealed)
OOP యొక్క రెండు మహా స్తంభాలు: ఇన్హెరిటెన్స్ & పాలిమార్ఫిజం! 🚀
ప్రకృతిలో తండ్రి పోలికలు, జన్యుపరమైన లక్షణాలు పిల్లలకు వారసత్వంగా రావడం చూస్తాం. అదేవిధంగా ఒక జీవి తన వాతావరణాన్ని బట్టి వివిధ రూపాలను స్వీకరించగలగడం (ఉదా: పాలు ఇచ్చే క్షీరదాలు, ఎగిరే పక్షులు అన్నీ 'జంతువు' అనే ఒకే మూలం నుండి వివిధ ప్రవర్తనలను ప్రదర్శించడం) పాలిమార్ఫిజం.
సాఫ్ట్వేర్ ఇంజనీరింగ్లో ఇన్హెరిటెన్స్ (Inheritance) ద్వారా వేలాది లైన్ల కామన్ కోడ్ను పదే పదే రాయకుండా ఒక్క మూల క్లాస్ (Base Class) లో భద్రపరిచి, అవసరమైన కొత్త ఫీచర్లను పిల్ల క్లాసుల్లో (Derived Classes) జోడించుకోవచ్చు. మరియు పాలిమార్ఫిజం (Polymorphism - virtual, override) ద్వారా ఒకే పేరెంట్ రిఫరెన్స్ వేరియబుల్తో వందలాది విభిన్న చైల్డ్ ఆబ్జెక్ట్లను రన్టైమ్లో అత్యంత సులభంగా నిర్వహించవచ్చు! ఈ కాన్సెప్ట్స్ మైక్రోసాఫ్ట్ ఆర్కిటెక్చర్ ఇంటర్వ్యూలలో అత్యధికంగా అడిగే ప్రశ్నలు. వీటిని క్లియర్ కోడ్ ఎగ్జాంపుల్స్తో లోతుగా అన్వేషిద్దాం!
1 🧬 ఇన్హెరిటెన్స్ (Inheritance) పునాది & "IS-A" రిలేషన్షిప్
ఇన్హెరిటెన్స్ అనేది ఇప్పటికే ఉన్న ఒక క్లాస్ (Base Class) యొక్క లక్షణాలు (Fields) మరియు ప్రవర్తనలను (Methods) మరొక కొత్త క్లాస్ (Derived Class) వారసత్వంగా పొందే సాంకేతిక ప్రక్రియ.
ఇన్హెరిటెన్స్ వాడటానికి ముందు ఎల్లప్పుడూ "IS-A" (ఇది ఒక...) పరీక్ష చేయాలి:
- ✅
SavingsAccount IS-A BankAccount(పొదుపు ఖాతా అనేది ఒక బ్యాంక్ ఖాతా). కాబట్టి ఇన్హెరిటెన్స్ సరైనది. - ✅
ElectricCar IS-A Vehicle(ఎలక్ట్రిక్ కారు అనేది ఒక వాహనం). ఇన్హెరిటెన్స్ సరైనది. - ❌
Car HAS-A Engine(కారు వద్ద ఇంజిన్ ఉంటుంది, కానీ కారు ఇంజిన్ కాదు!). దీనికి ఇన్హెరిటెన్స్ వాడకూడదు, Composition వాడాలి.
2 🔗 C# ఇన్హెరిటెన్స్ సింటాక్స్ (`:`) & ప్రొటెక్టెడ్ మెంబర్స్
C# లో ఇన్హెరిటెన్స్ చేయడానికి కోలన్ (:) సింబల్ ఉపయోగిస్తాం.
బేస్ క్లాస్లోని public మెంబర్లు ఎవరికైనా కనిపిస్తాయి. కానీ private మెంబర్లు చైల్డ్ క్లాస్కు కూడా అందవు!
బయటి ప్రపంచానికి కనిపించకూడదు, కానీ చైల్డ్ క్లాస్కు మాత్రం పూర్తి స్వేచ్ఛగా అందుబాటులో ఉండాలి అనుకున్నప్పుడు
మనం protected యాక్సెస్ మోడిఫైయర్ వాడాలి.
// 1. బేస్ క్లాస్ (Parent)
public class Account
{
public string AccountNumber { get; set; }
// protected: బయటికి కనిపించదు కానీ చైల్డ్ క్లాస్ నేరుగా వాడుకోవచ్చు!
protected decimal InternalBalance;
public void CheckBalance()
{
Console.WriteLine($"ఖాతా {AccountNumber} బ్యాలెన్స్: ₹{InternalBalance:N2}");
}
}
// 2. డిరైవ్డ్ క్లాస్ (Child) - Account నుండి వారసత్వం పొందింది
public class SavingsAccount : Account
{
public decimal InterestRate { get; set; } = 4.5m;
public void DepositWithBonus(decimal amount)
{
// InternalBalance ని చైల్డ్ లో నేరుగా యాక్సెస్ చేస్తున్నాం!
InternalBalance += amount + 100m; // ₹100 బోనస్
Console.WriteLine($"₹{amount:N2} జమ అయ్యింది (+₹100 బోనస్ లభించింది)!");
}
}
SavingsAccount sa = new SavingsAccount();
sa.AccountNumber = "SB-8921";
sa.DepositWithBonus(10000m);
sa.CheckBalance(); // బేస్ క్లాస్ మెథడ్!
// అవుట్పుట్: ఖాతా SB-8921 బ్యాలెన్స్: ₹10,100.00
3 🧱 `base` కీవర్డ్ & కన్స్ట్రక్టర్ ఎగ్జిక్యూషన్ ఆర్డర్ (`: base(...)`)
ఒక చైల్డ్ క్లాస్ ఆబ్జెక్ట్ క్రియేట్ అయినప్పుడు మెమరీలో ఏం జరుగుతుంది? తండ్రి లేకుండా కొడుకు పుట్టలేడు! అలాగే బేస్ క్లాస్ కన్స్ట్రక్టర్ రన్ అవ్వకుండా చైల్డ్ క్లాస్ ఆబ్జెక్ట్ ఏర్పడదు!
కన్స్ట్రక్టర్ల ఎగ్జిక్యూషన్ క్రమం (Order of Execution):
- మొదటగా Base Class Constructor రన్ అవుతుంది.
- ఆ తర్వాతే Derived Class Constructor రన్ అవుతుంది.
బేస్ క్లాస్ కన్స్ట్రక్టర్కు అవసరమైన పారామీటర్లను చైల్డ్ నుండి పంపించడానికి : base(...) సింటాక్స్ వాడతాం.
public class Device
{
public string SerialNumber { get; }
public string Manufacturer { get; }
public Device(string serial, string manufacturer)
{
SerialNumber = serial;
Manufacturer = manufacturer;
Console.WriteLine($"1. Device బేస్ కన్స్ట్రక్టర్ రన్ అయ్యింది: {Manufacturer}");
}
}
public class Smartphone : Device
{
public int CameraMegapixels { get; }
// base(...) ద్వారా బేస్ కన్స్ట్రక్టర్కు డేటా పంపుతున్నాం
public Smartphone(string serial, string manufacturer, int cameraMp)
: base(serial, manufacturer)
{
CameraMegapixels = cameraMp;
Console.WriteLine($"2. Smartphone చైల్డ్ కన్స్ట్రక్టర్ రన్ అయ్యింది: {CameraMegapixels}MP");
}
}
Smartphone phone = new Smartphone("SN-90812", "Samsung", 200);
// అవుట్పుట్:
// 1. Device బేస్ కన్స్ట్రక్టర్ రన్ అయ్యింది: Samsung
// 2. Smartphone చైల్డ్ కన్స్ట్రక్టర్ రన్ అయ్యింది: 200MP
4 🎭 పాలిమార్ఫిజం (Polymorphism) తత్వశాస్త్రం
గ్రీకు భాషలో Poly అంటే "అనేక", Morph అంటే "రూపాలు". కంప్యూటర్ సైన్స్లో పాలిమార్ఫిజం అంటే — ఒకే ఒక సాధారణ రిఫరెన్స్ వేరియబుల్ ద్వారా అనేక రకాల ఆబ్జెక్ట్లను వాటి నిర్దిష్ట రూపంలో ఆపరేట్ చేయగల సామర్థ్యం.
| రకం | ఎప్పుడు నిర్ణయించబడుతుంది? | C# ఇంప్లిమెంటేషన్ |
|---|---|---|
| Compile-Time (Static) Polymorphism | కోడ్ కంపైల్ అయ్యే సమయంలోనే | Method Overloading (ఒకే పేరుతో వేర్వేరు పారామీటర్ల మెథడ్స్) & Operator Overloading. |
| Runtime (Dynamic) Polymorphism | ప్రోగ్రామ్ రన్ అవుతున్న సమయంలో మెమరీలోని అసలైన ఆబ్జెక్ట్ ఆధారంగా | Method Overriding (virtual & override కీవర్డ్స్). |
5 🪄 `virtual` మరియు `override` మెకానిక్స్ — Runtime Method Dispatch
సాధారణంగా C# లో ఒక మెథడ్ పిలిచినప్పుడు, రిఫరెన్స్ వేరియబుల్ యొక్క టైప్ ఆధారంగా ఆ మెథడ్ ఎగ్జిక్యూట్ అవుతుంది. కానీ రన్టైమ్లో వేరియబుల్ దేనిని పాయింట్ చేస్తుందో ఆ అసలైన ఆబ్జెక్ట్ మెథడ్ రన్ అవ్వాలంటే C# లో 2 కీవర్డ్స్ తప్పనిసరి:
virtual(బేస్ క్లాస్లో): "నా పిల్ల క్లాసులు నన్ను తమ ఇష్టానుసారం మార్చుకోవడానికి (Override చేయడానికి) నేను అనుమతిస్తున్నాను!" అని పేరెంట్ ప్రకటించడం.override(చైల్డ్ క్లాస్లో): "నా పేరెంట్ ఇచ్చిన డీఫాల్ట్ పనిని పక్కనపెట్టి, నా స్వంత సరికొత్త రూపాన్ని నేను అమలు చేస్తున్నాను!" అని చైల్డ్ ధృవీకరించడం.
public class PaymentProcessor
{
// virtual మెథడ్ - చైల్డ్ ఓవర్రైడ్ చేసుకోవచ్చు
public virtual void ProcessPayment(decimal amount)
{
Console.WriteLine($"సాధారణ చెల్లింపు పూర్తయింది: ₹{amount:N2}");
}
}
public class UpiPayment : PaymentProcessor
{
public override void ProcessPayment(decimal amount)
{
Console.WriteLine($"⚡ UPI తక్షణ చెల్లింపు పూర్తయింది (జీరో ఫీజు): ₹{amount:N2}");
}
}
public class CreditCardPayment : PaymentProcessor
{
public override void ProcessPayment(decimal amount)
{
decimal fee = amount * 0.02m; // 2% ప్రాసెసింగ్ ఫీజు
Console.WriteLine($"💳 క్రెడిట్ కార్డ్ చెల్లింపు పూర్తయింది: ₹{amount:N2} (+₹{fee:N2} ఫీజు)");
}
}
// 🌟 పాలిమార్ఫిక్ మ్యాజిక్: బేస్ క్లాస్ లిస్ట్లో అన్ని రకాల చైల్డ్స్!
List queue = new()
{
new UpiPayment(),
new CreditCardPayment(),
new PaymentProcessor()
};
foreach (var processor in queue)
{
// రన్టైమ్లో ఆయా ఆబ్జెక్ట్ యొక్క సరైన override మెథడ్ మాత్రమే రన్ అవుతుంది!
processor.ProcessPayment(5000m);
}
CLR అంతర్గత రహస్యం (vtable): ప్రతి క్లాస్కు ఒక Virtual Method Table (vtable) ఉంటుంది. ఆబ్జెక్ట్ క్రియేట్ అయినప్పుడు దాని Type Handle ఈ టేబుల్ను పాయింట్ చేస్తుంది. కంపైలర్ డైరెక్ట్ జంప్ కోడ్ రాయకుండా, టేబుల్లోని ఫంక్షన్ పాయింటర్ను లుకప్ చేసి కాల్ చేస్తుంది. దీన్నే Dynamic Dispatch అంటారు.
6 ⚠️ Method Overriding vs Method Hiding (`new` కీవర్డ్) — ఇంటర్వ్యూ క్లాసిక్
మైక్రోసాఫ్ట్ మరియు ప్రఖ్యాత టెక్ కంపెనీల ఇంటర్వ్యూలలో 100% అడిగే క్వశ్చన్: "What is the difference between overriding a method and hiding a method using the `new` keyword?"
public class BaseClass
{
public virtual void MethodA() => Console.WriteLine("Base MethodA");
public void MethodB() => Console.WriteLine("Base MethodB");
}
public class DerivedClass : BaseClass
{
// 1. OVERRIDE: వర్చువల్ టేబుల్ను నిజంగా అప్డేట్ చేస్తుంది
public override void MethodA() => Console.WriteLine("Derived MethodA (Overridden)");
// 2. NEW (Hiding): బేస్ మెథడ్ను కేవలం దాచిపెడుతుంది (Shadowing)
public new void MethodB() => Console.WriteLine("Derived MethodB (Hidden)");
}
// 🧪 అసలైన టెస్ట్ ఇక్కడే ఉంది:
BaseClass obj = new DerivedClass(); // బేస్ రిఫరెన్స్, చైల్డ్ ఆబ్జెక్ట్!
obj.MethodA(); // 👉 అవుట్పుట్: Derived MethodA (Overridden) -> పాలిమార్ఫిజం పనిచేసింది!
obj.MethodB(); // 👉 అవుట్పుట్: Base MethodB -> షాక్! new వాడితే బేస్ క్లాస్ మెథడే రన్ అవుతుంది!
💡 ముఖ్యమైన టేకావే:
• override వాడితే, రిఫరెన్స్ వేరియబుల్ ఏ టైప్ అయినా సరే రన్టైమ్లో ఉన్న అసలైన చైల్డ్ ఆబ్జెక్ట్ మెథడ్ రన్ అవుతుంది (ట్రూ పాలిమార్ఫిజం).
• new వాడితే, అది పాలిమార్ఫిజం కాదు. మీరు బేస్ టైప్ ద్వారా పిలిస్తే బేస్ మెథడ్, చైల్డ్ టైప్ ద్వారా పిలిస్తే చైల్డ్ మెథడ్ రన్ అవుతుంది.
7 🔒 `sealed` క్లాసెస్ & `sealed` మెథడ్స్ — వారసత్వానికి సంకెళ్లు
కొన్ని క్లాసులను ఎవరూ ఇన్హెరిట్ చేసుకోకూడదని మనం కోరుకుంటాం.
ఉదాహరణకు సెక్యూరిటీ క్రిప్టోగ్రఫీ క్లాస్ను ఎవరైనా ఇన్హెరిట్ చేసి హాకింగ్ లాజిక్ రాయకుండా నిరోధించడానికి sealed కీవర్డ్ వాడతాం.
// 1. సీల్డ్ క్లాస్ - దీన్ని ఎవరూ ఇన్హెరిట్ చేసుకోలేరు
public sealed class SecurityTokenProvider
{
public string GenerateJwt() => Guid.NewGuid().ToString();
}
// public class HackerProvider : SecurityTokenProvider { }
// ❌ కంపైలర్ ఎర్రర్: Cannot derive from sealed type 'SecurityTokenProvider'!
// ----------------------------------------------------
// 2. సీల్డ్ మెథడ్ - చైల్డ్ లో ఫర్దర్ ఓవర్రైడింగ్ ఆపడం
public class Shape
{
public virtual void Draw() => Console.WriteLine("Drawing Shape");
}
public class Circle : Shape
{
// sealed override: ఇకపై Circle ను ఇన్హెరిట్ చేసుకునే క్లాసులు Draw ని మార్చలేవు!
public sealed override void Draw() => Console.WriteLine("Drawing Circle");
}
⚡ Performance Advantage: sealed క్లాసులు కేవలం భద్రత కోసమే కాదు!
.NET JIT కంపైలర్ సీల్డ్ క్లాసులకు vtable లుకప్ చేయకుండా నేరుగా ఇన్లైన్ అసెంబ్లీ కోడ్ (Devirtualization) జనరేట్ చేస్తుంది.
దీనివల్ల మైక్రోసెకన్ల విలువైన రన్టైమ్ పెర్ఫార్మెన్స్ పెరుగుతుంది!
8 🌳 C# లో అల్టిమేట్ రూట్ క్లాస్: `System.Object`
C# లో ప్రతి ఒక్క క్లాస్, స్ట్రక్ట్, అర్రే లేదా డేటా టైప్ అంతిమంగా System.Object (లేదా చిన్న అక్షరాలతో object) నుండే పుడతాయి.
System.Object మనకు అందించే 4 ముఖ్యమైన వర్చువల్ మెథడ్స్:
ToString(): ఆబ్జెక్ట్ను స్ట్రింగ్ రూపంలోకి మారుస్తుంది (డీఫాల్ట్గా క్లాస్ పేరు ఇస్తుంది, మనం ఓవర్రైడ్ చేసుకోవాలి).Equals(object obj): రెండు ఆబ్జెక్టులు సమానమా కాదా పరీక్షిస్తుంది.GetHashCode(): హాష్ టేబుల్స్ / డిక్షనరీల కోసం ఇంటీజర్ హాష్ కోడ్ ఇస్తుంది.GetType(): రన్టైమ్ టైప్ మెటాడేటాను ఇస్తుంది (Reflection).
public class Customer
{
public int CustId { get; set; }
public string Name { get; set; }
public string City { get; set; }
// System.Object లోని ToString() ను అర్థవంతంగా ఓవర్రైడ్ చేయడం
public override string ToString()
{
return $"కస్టమర్ #{CustId}: {Name} ({City})";
}
}
Customer c = new Customer { CustId = 101, Name = "వెంకటేశ్వర్లు", City = "విజయవాడ" };
// Console.WriteLine ఆటోమేటిక్గా ToString() ని పిలుస్తుంది!
Console.WriteLine(c);
// అవుట్పుట్: కస్టమర్ #101: వెంకటేశ్వర్లు (విజయవాడ)
9 🔍 టైప్ కాస్టింగ్ — Upcasting, Downcasting & `is`, `as` ఆపరేటర్లు
ఇన్హెరిటెన్స్ హైరార్కీలో ఆబ్జెక్ట్లను పైకి లేదా కిందకి మార్చడాన్ని టైప్ కాస్టింగ్ అంటారు:
- Upcasting (పైకి): చైల్డ్ ఆబ్జెక్ట్ను పేరెంట్ టైప్లోకి మార్చడం. ఇది ఎల్లప్పుడూ 100% సేఫ్, ఆటోమేటిక్గా జరుగుతుంది (ఉదా:
Animal a = new Dog();). - Downcasting (కిందికి): పేరెంట్ రిఫరెన్స్ను చైల్డ్ టైప్లోకి మార్చడం. ఇది ప్రమాదకరం. ఒకవేళ ఆ వేరియబుల్లో నిజమైన చైల్డ్ లేకపోతే
InvalidCastExceptionవచ్చి ప్రోగ్రామ్ క్రాష్ అవుతుంది!
సురక్షితమైన డౌన్కాస్టింగ్ కోసం ఆధునిక C# లో is ప్యాటర్న్ మ్యాచింగ్ వాడతాం:
public class Vehicle { }
public class Car : Vehicle { public void PlayRadio() => Console.WriteLine("రేడియో ప్లే అవుతోంది 🎵"); }
public class Drone : Vehicle { public void Fly() => Console.WriteLine("డ్రోన్ ఎగురుతోంది 🚁"); }
Vehicle v = new Car(); // Upcasting (Safe)
// ✅ మోడ్రన్ C# 'is' ప్యాటర్న్ మ్యాచింగ్ - సేఫ్ కాస్టింగ్ & వేరియబుల్ అసైన్మెంట్ ఒక్కచోటే!
if (v is Car myCar)
{
myCar.PlayRadio(); // నేరుగా సురక్షితంగా వాడవచ్చు!
}
// పాత 'as' ఆపరేటర్ పద్ధతి (విఫలమైతే null ఇస్తుంది)
Drone d = v as Drone;
if (d != null)
{
d.Fly();
}
else
{
Console.WriteLine("ఇది డ్రోన్ కాదు, కాబట్టి Fly చేయలేము!");
}
10 📐 Liskov Substitution Principle (LSP) — SOLID పునాది
ప్రపంచ ప్రఖ్యాత సాఫ్ట్వేర్ సూత్రాలు అయిన SOLID Principles లోని 'L' అక్షరమే Liskov Substitution Principle (లిస్కోవ్ సబ్స్టిట్యూషన్ సూత్రం).
LSP ఉల్లంఘనకు క్లాసిక్ ఉదాహరణ: Rectangle (దీర్ఘచతురస్రం) ను బేస్ క్లాస్గా చేసి Square (చతురస్రం) ను చైల్డ్ చేయడం.
చతురస్రంలో Width మార్చితే Height కూడా మారిపోతుంది. దీనివల్ల Rectangle ఆశించిన ప్రవర్తన దెబ్బతింటుంది.
అందువల్ల తప్పుడు ఇన్హెరిటెన్స్ చేయకుండా సరైన అబ్స్ట్రాక్షన్ డిజైన్ చేయాలి.
11 🥊 Inheritance vs Composition — "IS-A" vs "HAS-A"
డిజైన్ ప్యాటర్న్స్ రచయితలు (Gang of Four - GoF) ఇచ్చిన ప్రఖ్యాత సూత్రం: "Favor object composition over class inheritance."
- ఇన్హెరిటెన్స్ ఎప్పుడు వాడాలి?: నిజమైన IS-A సంబంధం ఉన్నప్పుడు మరియు పేరెంట్ క్లాస్ కోడ్ స్థిరంగా ఉన్నప్పుడు (ఉదా: GUI Controls, Framework Base Classes).
- కంపోజిషన్ ఎప్పుడు వాడాలి?: HAS-A సంబంధం ఉన్నప్పుడు (ఉదా:
Car HAS-A Engine,Order HAS-A List<OrderItem>). కంపోజిషన్ వల్ల క్లాసుల మధ్య టైట్ కప్లింగ్ తగ్గి, టెస్టింగ్ & మెయింటెనెన్స్ సులభమవుతుంది.
12 🚗 రియల్-వరల్డ్ ప్రాజెక్ట్ — ఎంటర్ప్రైజ్ స్మార్ట్ టోల్ గేట్ & ఫ్లీట్ సిస్టమ్ (Smart Toll Plaza Engine)
ఈ అధ్యాయంలో నేర్చుకున్న Inheritance, Constructor chaining (base), Virtual/Override polymorphism,
మరియు sealed క్లాసులన్నింటినీ ఉపయోగించి ఒక పూర్తి స్థాయి స్మార్ట్ టోల్ ప్లాజా ఇంజిన్ (Smart Toll Plaza Engine v1.0) నిర్మిద్దాం.
using System;
using System.Collections.Generic;
Console.OutputEncoding = System.Text.Encoding.UTF8;
Console.WriteLine("=================================================");
Console.WriteLine("🛣️ హైదరాబాద్ ఔటర్ రింగ్ రోడ్ - స్మార్ట్ టోల్ ప్లాజా v1.0");
Console.WriteLine("=================================================\n");
// 1. బేస్ క్లాస్ (Base Vehicle)
public class Vehicle
{
public string RegistrationNumber { get; }
public string Model { get; }
public decimal BaseTollRate { get; }
public Vehicle(string regNo, string model, decimal baseRate)
{
RegistrationNumber = regNo;
Model = model;
BaseTollRate = baseRate;
}
// వర్చువల్ మెథడ్ - చైల్డ్ క్లాసులు టోల్ లెక్కలను ఓవర్రైడ్ చేయవచ్చు
public virtual decimal CalculateToll()
{
return BaseTollRate;
}
public virtual void PrintPass(decimal finalToll)
{
Console.WriteLine($"🚗 [{this.GetType().Name,-15}] వాహనం: {RegistrationNumber,-12} ({Model,-15}) | టోల్ ఫీజు: ₹{finalToll:N2}");
}
}
// 2. చైల్డ్ క్లాస్ 1: ఎలక్ట్రిక్ కార్ (50% గ్రీన్ డిస్కౌంట్)
public class ElectricCar : Vehicle
{
public int BatteryCapacityKwh { get; }
public ElectricCar(string regNo, string model, int batteryKwh)
: base(regNo, model, 120.00m) // స్టాండర్డ్ కార్ టోల్ ₹120
{
BatteryCapacityKwh = batteryKwh;
}
public override decimal CalculateToll()
{
// పర్యావరణ అనుకూల వాహనం కాబట్టి 50% రాయితీ
return BaseTollRate * 0.50m;
}
}
// 3. చైల్డ్ క్లాస్ 2: కమర్షియల్ ట్రక్ (యాక్సిల్స్ ఆధారంగా అదనపు ఛార్జీ)
public class CommercialTruck : Vehicle
{
public int AxleCount { get; }
public CommercialTruck(string regNo, string model, int axles)
: base(regNo, model, 350.00m)
{
AxleCount = axles;
}
public override decimal CalculateToll()
{
// 2 కంటే ఎక్కువ యాక్సిల్స్ ఉంటే ఒక్కో అదనపు యాక్సిల్కు ₹100 అదనం
decimal extraAxlePenalty = (AxleCount > 2) ? (AxleCount - 2) * 100.00m : 0m;
return BaseTollRate + extraAxlePenalty;
}
}
// 4. చైల్డ్ క్లాస్ 3: ఎమర్జెన్సీ అంబులెన్స్ (100% ఉచితం - sealed క్లాస్!)
public sealed class EmergencyAmbulance : Vehicle
{
public string HospitalName { get; }
public EmergencyAmbulance(string regNo, string hospital)
: base(regNo, "ఫోర్స్ ట్రావెలర్ అంబులెన్స్", 0m)
{
HospitalName = hospital;
}
public sealed override decimal CalculateToll() => 0.00m; // సంపూర్ణ మినహాయింపు
}
// 5. టోల్ ప్లాజా మేనేజర్ - పాలిమార్ఫిక్ కలెక్షన్ ప్రాసెసింగ్
public class TollPlazaBooth
{
public decimal TotalRevenueCollected { get; private set; }
public int TotalVehiclesPassed { get; private set; }
public void ProcessTollLane(List trafficQueue)
{
Console.WriteLine("🚦 టోల్ బూత్ లేన్ ప్రాసెసింగ్ ప్రారంభమైంది...\n");
foreach (var v in trafficQueue)
{
// 🌟 డైనమిక్ పాలిమార్ఫిజం: రన్టైమ్లో సరైన CalculateToll() రన్ అవుతుంది!
decimal toll = v.CalculateToll();
v.PrintPass(toll);
TotalRevenueCollected += toll;
TotalVehiclesPassed++;
}
}
}
// డ్రైవర్ కోడ్: ఫ్లీట్ సిమ్యులేషన్
List tollQueue = new()
{
new Vehicle("TS-09-EA-1122", "హ్యుందాయ్ క్రెటా", 120.00m),
new ElectricCar("TS-07-EV-9999", "టాటా నెక్సాన్ EV", 40),
new CommercialTruck("AP-16-TX-4455", "భారత్బెంజ్ 16-వీలర్", 4),
new EmergencyAmbulance("TS-10-AMB-108", "అపోలో హాస్పిటల్స్"),
new CommercialTruck("KA-01-HG-7812", "అశోక్ లేలాండ్ 6-వీలర్", 2)
};
TollPlazaBooth tollBooth = new TollPlazaBooth();
tollBooth.ProcessTollLane(tollQueue);
Console.WriteLine($"\n📊 నేటి టోల్ ప్లాజా ఆడిట్ నివేదిక:");
Console.WriteLine($"మొత్తం ప్రయాణించిన వాహనాలు: {tollBooth.TotalVehiclesPassed}");
Console.WriteLine($"మొత్తం వసూలైన టోల్ రెవెన్యూ : ₹{tollBooth.TotalRevenueCollected:N2}");
Console.WriteLine("=================================================");
💻 ఈ టోల్ ప్లాజా ప్రాజెక్ట్ను లైవ్ కంపైలర్లో రన్ చేసి చూడండి!
Vehicle బేస్ క్లాస్, ElectricCar రాయితీలు, CommercialTruck పెనాల్టీలు మరియు Ambulance ఉచిత పాస్ల పాలిమార్ఫిక్ ప్రవర్తనను పరిశీలించండి.
13 🎓 ఇంటర్వ్యూ ప్రశ్నలు, బెస్ట్ ప్రాక్టీసెస్ & 5 ఇంటరాక్టివ్ క్విజ్ ప్రశ్నలు
టాప్ ఇంటర్వ్యూ ప్రశ్నలు & సమాధానాలు:
Q1: C# లో మల్టిపుల్ క్లాస్ ఇన్హెరిటెన్స్ ఎందుకు సపోర్ట్ చేయదు?
జవాబు: "Deadly Diamond of Death" సమస్యను నివారించడానికి. ఒక క్లాస్ రెండు పేరెంట్స్ నుండి ఒకే పేరున్న మెథడ్ను ఇన్హెరిట్ చేసుకుంటే ఏ పేరెంట్ మెథడ్ రన్ అవ్వాలో అస్పష్టత ఏర్పడుతుంది. ఈ సమస్యను అరికట్టడానికి C# సింగిల్ క్లాస్ ఇన్హెరిటెన్స్ మాత్రమే అనుమతిస్తూ, మల్టిపుల్ కాంట్రాక్టుల కోసం Interfaces ను అందిస్తుంది.
Q2: sealed క్లాస్ వల్ల రన్టైమ్ పెర్ఫార్మెన్స్ ఎలా పెరుగుతుంది?
జవాబు: JIT (Just-In-Time) కంపైలర్కు ఆ క్లాస్ నుండి మరే ఇతర డిరైవ్డ్ క్లాసులు ఉండవని ఖచ్చితంగా తెలుస్తుంది. కాబట్టి వర్చువల్ మెథడ్ టేబుల్ (vtable) లుకప్ అవసరం లేకుండా నేరుగా ఇన్-లైన్ మెషిన్ కోడ్ను (Devirtualization) ఉత్పత్తి చేస్తుంది.
🧠 మీ నాలెడ్జ్ చెక్ చేసుకోండి — 5 ఇంటరాక్టివ్ క్విజ్ ప్రశ్నలు
❓ ప్రశ్న 1: చైల్డ్ క్లాస్ ఆబ్జెక్ట్ క్రియేట్ చేసినప్పుడు ఏ కన్స్ట్రక్టర్ మొదటగా ఎగ్జిక్యూట్ అవుతుంది?
❓ ప్రశ్న 2: బేస్ క్లాస్లోని ఒక మెథడ్ను చైల్డ్ క్లాస్ మార్చడానికి బేస్ క్లాస్లో ఏ కీవర్డ్ వాడాలి?
virtual. బేస్ క్లాస్ virtual అని అనుమతి ఇస్తేనే చైల్డ్ క్లాస్ override చేయగలదు.
❓ ప్రశ్న 3: BaseClass b = new DerivedClass(); b.Method(); అన్నప్పుడు చైల్డ్లో new కీవర్డ్ ఉంటే ఏ మెథడ్ రన్ అవుతుంది?
BaseClass లోని మెథడ్ మాత్రమే రన్ అవుతుంది. ఎందుకంటే new అనేది పాలిమార్ఫిజం కాదు (Method Hiding మాత్రమే). అది వర్చువల్ టేబుల్ను అప్డేట్ చేయదు.
❓ ప్రశ్న 4: C# లోని అన్ని టైప్స్ అంతిమంగా ఏ బేస్ క్లాస్ నుండి పుడతాయి?
System.Object (లేదా object).