कोई भी तरीका अतिश्योक्तिपूर्ण (= 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तरीके बना सकते हैं - चाहे आप जिस तरीके को छिपा रहे हैं वह आभासी है या नहीं।
यह गुणों और घटनाओं पर भी लागू होता है - उन्हें नीचे दिए गए तरीकों के रूप में दर्शाया जाता है।