कोई भी तरीका अतिश्योक्तिपूर्ण (= virtual
) हो सकता है या नहीं। निर्णय विधि को परिभाषित करने वाले व्यक्ति द्वारा किया जाता है:
class Person
{
public String GetPersonType()
{
return "person";
}
public virtual String GetName()
{
return "generic name";
}
}
अब आप उन तरीकों को ओवरराइड कर सकते हैं, जो बहुत अधिक उपयोग योग्य हैं:
class Friend : Person
{
public Friend() : this("generic name") { }
public Friend(String name)
{
this._name = name;
}
public override String GetName()
{
return _name;
}
}
लेकिन आप इस GetPersonType
विधि को ओवरराइड नहीं कर सकते क्योंकि यह आभासी नहीं है।
आइए उन वर्गों के दो उदाहरण बनाएं:
Person person = new Person();
Friend friend = new Friend("Onotole");
जब गैर-आभासी विधि GetPersonType
को Fiend
उदाहरण के द्वारा पुकारा जाता है तो यह वास्तव Person.GetPersonType
में कहा जाता है:
Console.WriteLine(friend.GetPersonType());
जब आभासी विधि GetName
को Friend
उदाहरण के द्वारा पुकारा जाता है तो उसे Friend.GetName
कहा जाता है:
Console.WriteLine(friend.GetName());
जब आभासी विधि GetName
को Person
उदाहरण के द्वारा पुकारा जाता है तो उसे Person.GetName
कहा जाता है:
Console.WriteLine(person.GetName());
जब गैर-आभासी विधि को विधि कहा जाता है, तो निकाय को देखा नहीं जाता है - संकलक को पहले से ही उस वास्तविक विधि का पता चल जाता है जिसे कॉल करने की आवश्यकता होती है। जबकि वर्चुअल मेथड कंपाइलर के साथ यह सुनिश्चित नहीं किया जा सकता है कि किसे कॉल करना है, और इसे क्लास पदानुक्रम में रनटाइम पर देखा जाता है नीचे से ऊपर तक उदाहरण के प्रकार पर शुरू होता है जिसे विधि कहा जाता है: क्योंकि friend.GetName
यह Friend
क्लास से शुरू होता है और person.GetName
कक्षा के लिए शुरू होता है Person
और उसे वहीं पाता है।
कभी-कभी आप एक उपवर्ग बनाते हैं, एक आभासी विधि को ओवरराइड करते हैं और आप पदानुक्रम में कोई अधिक ओवरराइड्स नहीं चाहते हैं - आप इसके लिए उपयोग sealed override
करते हैं (यह कहते हुए कि आप अंतिम हैं जो विधि को ओवरराइड करते हैं):
class Mike : Friend
{
public sealed override String GetName()
{
return "Mike";
}
}
लेकिन कभी-कभी आपका दोस्त माइक अपने लिंग को बदलने का फैसला करता है और इस तरह उसका नाम ऐलिस :) आप या तो मूल कोड बदल सकते हैं या इसके बजाय माइक को उपवर्गित कर सकते हैं:
class Alice : Mike
{
public new String GetName()
{
return "Alice";
}
}
यहां आप एक ही नाम (अब आपके पास दो) के साथ एक पूरी तरह से अलग विधि बनाते हैं। किस विधि और कब कहा जाता है? यह इस बात पर निर्भर करता है कि आप इसे कैसे कहते हैं:
Alice alice = new Alice();
Console.WriteLine(alice.GetName());
Console.WriteLine(((Mike)alice).GetName());
जब आप इसे Alice
कॉल करते हैं Alice.GetName
, तो जब आप कॉल करते हैं , तो Mike
आप कॉल करते हैं Mike.GetName
। कोई रनटाइम लुकअप यहां नहीं किया गया है - क्योंकि दोनों विधियाँ गैर-आभासी हैं।
आप हमेशा new
तरीके बना सकते हैं - चाहे आप जिस तरीके को छिपा रहे हैं वह आभासी है या नहीं।
यह गुणों और घटनाओं पर भी लागू होता है - उन्हें नीचे दिए गए तरीकों के रूप में दर्शाया जाता है।