सार फ़ंक्शन और वर्चुअल फ़ंक्शन के बीच अंतर क्या है?


1578

सार फ़ंक्शन और वर्चुअल फ़ंक्शन के बीच अंतर क्या है? आभासी या सार का उपयोग करने के लिए किन मामलों में सिफारिश की जाती है? सबसे अच्छा तरीका कौन सा है?


271
एक सार फ़ंक्शन को ओवरराइड करना पड़ता है जबकि एक वर्चुअल फ़ंक्शन ओवरराइड किया जा सकता है।
जॉर्डन पैरामर

15
वर्चुअल फ़ंक्शंस में बेस क्लास में एक डिफ़ॉल्ट / सामान्य कार्यान्वयन हो सकता है।
मार्टिन

5
यहाँ मुख्य शब्द सार है ; वे मौजूद नहीं हैं और केवल एक अस्पष्ट विचार है कि फ़ंक्शन क्या है (विधि हस्ताक्षर)
कोल जॉनसन

जवाबों:


2734

एक सार फ़ंक्शन में कार्यक्षमता नहीं हो सकती। आप मूल रूप से कह रहे हैं, किसी भी बाल वर्ग को इस विधि का अपना संस्करण देना होगा, हालांकि मूल कक्षा में इसे लागू करने की कोशिश करना भी सामान्य है।

एक आभासी कार्य , मूल रूप से कह रहा है देखो, यहाँ वह कार्यक्षमता है जो बाल वर्ग के लिए पर्याप्त हो सकती है या नहीं भी। तो अगर यह काफी अच्छा है, तो इस विधि का उपयोग करें, यदि नहीं, तो मुझे ओवरराइड करें, और अपनी कार्यक्षमता प्रदान करें।


396
और निश्चित रूप से, यदि आप एक आभासी विधि को ओवरराइड करते हैं, तो आप हमेशा आधार विधि को कॉल करके मूल विधि का उल्लेख कर सकते हैं। फू (...)
ब्रैन

196
धन्यवाद। यह MSDN प्रलेखन में किसी भी चीज़ की तुलना में बहुत बेहतर और आसान विवरण है। (इसे पढ़ने के पाँच मिनट बाद मुझे सिरदर्द हुआ: msdn.microsoft.com/en-us/library/aa645767(v=vs.71).aspx )
जेक

15
जावा से आ रहा है, मैं थोड़ा हैरान था कि हमें इसे पूरी तरह से आभासी बनाने की आवश्यकता क्यों है, जब तक मैं इसे नहीं पढ़ता: stackoverflow.com/a/1062126/193634
रोजी कासिम

4
@MeqDotNet इसका मतलब है कि अगर आप मेरे कार्यान्वयन को पसंद करते हैं, तो मुझे खुद से बेहतर न लिखें :)
उस्मान यूनास

16
यह Microsoft संदर्भ पुस्तकालय में होना चाहिए जिसे मैंने 10 मिनट पढ़ने और फिर भी भ्रमित होने में खर्च किया।
सैमचेन २ Sam

302

एक सार फ़ंक्शन का कोई कार्यान्वयन नहीं है और इसे केवल एक सार वर्ग पर घोषित किया जा सकता है। यह व्युत्पन्न वर्ग को एक कार्यान्वयन प्रदान करने के लिए मजबूर करता है।

एक आभासी फ़ंक्शन एक डिफ़ॉल्ट कार्यान्वयन प्रदान करता है और यह एक अमूर्त वर्ग या एक गैर-अमूर्त वर्ग पर मौजूद हो सकता है।

उदाहरण के लिए:

public abstract class myBase
{
    //If you derive from this class you must implement this method. notice we have no method body here either
    public abstract void YouMustImplement();

    //If you derive from this class you can change the behavior but are not required to
    public virtual void YouCanOverride()
    { 
    }
}

public class MyBase
{
   //This will not compile because you cannot have an abstract method in a non-abstract class
    public abstract void YouMustImplement();
}

28
नमूना कोड को देखने के लिए बहुत उपयोगी है - जवाबों में विभिन्न स्पष्टीकरण को बहुत स्पष्ट करने में मदद करता है।
21:39 पर सिमोन तिवारी

2
मैंने पिछले संस्करण के उत्तर को वापस ले लिया: दो कक्षाएं सिर्फ उदाहरण हैं, पहली कक्षा संकलन करेगी क्योंकि यह सार के रूप में चिह्नित है, दूसरी नहीं। MyBase किसी अन्य वर्ग से विरासत में मिला है या नहीं अप्रासंगिक है।
डर्क

2
क्या आपकी MyBaseकक्षा को किसी तरह अमूर्त वर्ग को लागू नहीं करना है ? मैं अक्सर ऐसा नहीं करता, इसलिए मुझसे गलती हो सकती है। मुझे वह आपके उदाहरण में नहीं दिखता।
jp2code

2
MyBase के ऊपर के उदाहरण में दिखाया जा रहा है कि आप क्या नहीं कर सकते। यह है कि आप एक गैर सार वर्ग में एक सार पद्धति नहीं कर सकते हैं
जोशबर्के

80
  1. केवल abstractवर्गों में ही abstractसदस्य हो सकते हैं ।
  2. एक गैर- abstractवर्ग जो एक abstractवर्ग से विरासत में मिला है, उसके सदस्य होने चाहिएoverrideabstract
  3. एक abstractसदस्य निहित है virtual
  4. एक abstractसदस्य कोई भी कार्यान्वयन प्रदान नहीं कर सकता ( कुछ भाषाओं में abstractकहा जाता pure virtualहै)।

नंबर 3 मेरे लिए कोई मतलब नहीं है। मुझे लगता है कि आपके कहने का मतलब है "एक अमूर्त वर्ग का सदस्य अंतर्निहित रूप से आभासी है" (यानी, आप यह निर्दिष्ट करने के लिए कार्यक्षमता प्रदान कर सकते हैं कि यह आभासी है)।
होबो स्पाइडर

5
नहीं, मेरा मतलब वही था जो मैंने लिखा था। एक अमूर्त वर्ग का सदस्य virtualया गैर हो सकता है virtual। एक abstractसदस्य (यानी अमूर्त संपत्ति, अमूर्त विधि) एक आभासी विधि की तरह है, यानी आप इसे ओवरराइड कर सकते हैं, सिवाय इसके कि यह अपने आप में एक डिफ़ॉल्ट कार्यान्वयन नहीं करता है।
मेहरदाद अफश्री

उद्धृत "सार सदस्य" अंतर्निहित रूप से "आभासी है।" लेकिन मैंने कहीं देखा, किसी ने स्पष्ट रूप से "आभासी" कीवर्ड जोड़कर अमूर्त सदस्य बनाए थे। जो आवश्यक नहीं है और इसे प्रभावित करता है, इससे मुझे तब तक संदेह होता है जब तक कि मैं आपके उत्तर को नहीं पढ़ता।
bonCodigo

कृपया बिंदु 4 के लिए सहायक संदर्भों को शामिल करें। और आपकी पोस्ट कुछ और नहीं लाती है जो पिछले वाले पहले से नहीं थे।
राफेल

यह केवल स्पष्टीकरण के साथ बयानों का एक गुच्छा है।
रिवर्स इंजीनियर

61

आपको हमेशा एक सार फ़ंक्शन को ओवरराइड करना चाहिए।

इस प्रकार:

  • सार कार्य - जब उत्तराधिकारी को अपना कार्यान्वयन प्रदान करना होगा
  • आभासी - जब यह तय करने के लिए वारिस पर निर्भर है

37

सार समारोह:

  1. इसे केवल अमूर्त वर्ग के अंदर घोषित किया जा सकता है।
  2. इसमें केवल विधि घोषणा है जिसमें अमूर्त वर्ग में कार्यान्वयन नहीं है।
  3. इसे व्युत्पन्न वर्ग में ओवरराइड किया जाना चाहिए।

वर्चुअल फ़ंक्शन:

  1. इसे अमूर्त के साथ-साथ गैर अमूर्त वर्ग के अंदर भी घोषित किया जा सकता है।
  2. इसमें विधि कार्यान्वयन शामिल है।
  3. यह ओवरराइड हो सकता है।

29

सार विधि: जब किसी वर्ग में एक सार पद्धति होती है, तो उस कक्षा को सार के रूप में घोषित किया जाना चाहिए। अमूर्त पद्धति का कोई कार्यान्वयन नहीं है और इस प्रकार, उस अमूर्त वर्ग से प्राप्त होने वाली कक्षाएं, इस अमूर्त पद्धति के लिए एक कार्यान्वयन प्रदान करना चाहिए।

आभासी विधि: एक कक्षा में एक आभासी विधि हो सकती है। वर्चुअल पद्धति का एक कार्यान्वयन है। जब आपके पास वर्चुअल विधि वाली कक्षा से विरासत में मिलता है, तो आप आभासी पद्धति को ओवरराइड कर सकते हैं और अतिरिक्त तर्क प्रदान कर सकते हैं, या तर्क को अपने स्वयं के कार्यान्वयन के साथ बदल सकते हैं।

कब क्या उपयोग करें: कुछ मामलों में, आप जानते हैं कि कुछ प्रकारों में एक विशिष्ट विधि होनी चाहिए, लेकिन, आपको नहीं पता कि इस पद्धति का क्या कार्यान्वयन होना चाहिए।
ऐसे मामलों में, आप एक इंटरफ़ेस बना सकते हैं जिसमें इस हस्ताक्षर के साथ एक विधि है। हालांकि, अगर आपके पास ऐसा कोई मामला है, लेकिन आप जानते हैं कि उस इंटरफ़ेस के कार्यान्वयनकर्ताओं के पास एक अन्य सामान्य विधि भी होगी (जिसके लिए आप पहले से ही कार्यान्वयन प्रदान कर सकते हैं), तो आप एक सार वर्ग बना सकते हैं। इस अमूर्त वर्ग में तब अमूर्त विधि (जो अतिरंजित होनी चाहिए) शामिल है, और एक अन्य विधि जिसमें 'सामान्य' तर्क शामिल है।

एक वर्चुअल पद्धति का उपयोग किया जाना चाहिए यदि आपके पास एक वर्ग है जिसे सीधे उपयोग किया जा सकता है, लेकिन जिसके लिए आप चाहते हैं कि उत्तराधिकारी कुछ व्यवहार को बदलने में सक्षम हों, हालांकि यह अनिवार्य नहीं है।


29

स्पष्टीकरण: उपमाओं के साथ। उम्मीद है कि यह आपकी मदद करेगा।

प्रसंग

मैं एक इमारत की 21 वीं मंजिल पर काम करता हूं। और मैं आग के बारे में पागल हूँ। हर अब और फिर, दुनिया में कहीं न कहीं, एक आग एक आकाश खुरच रही है। लेकिन सौभाग्य से हमारे यहाँ एक निर्देश पुस्तिका है कि आग लगने पर क्या करना है:

आग बुझाने का दर्वाज़ा()

  1. सामान इकट्ठा मत करो
  2. आग से बचकर चलना
  3. इमारत से बाहर चलो

यह मूल रूप से एक आभासी विधि है जिसे FireEcape () कहा जाता है

आभासी विधि

यह योजना 99% परिस्थितियों के लिए बहुत अच्छी है। यह एक मूल योजना है जो काम करती है। लेकिन 1% संभावना है कि आग से बच गया या क्षतिग्रस्त हो गया है जिस स्थिति में आप पूरी तरह से खराब हो गए हैं और जब तक आप कुछ कठोर कार्रवाई नहीं करते हैं तब तक आप टोस्ट बन जाएंगे। आभासी तरीकों से आप बस इतना कर सकते हैं: आप योजना के अपने स्वयं के संस्करण के साथ मूल फायरएस्केप () योजना को ओवरराइड कर सकते हैं:

  1. खिड़की के पास भागो
  2. खिड़की से बाहर कूदो
  3. नीचे तक सुरक्षित रूप से पैराशूट

दूसरे शब्दों में, वर्चुअल तरीके एक मूल योजना प्रदान करते हैं, जिसे यदि आप की आवश्यकता होती है, तो ओवरराइड किया जा सकता है । यदि प्रोग्रामर इसे उचित समझे तो उपवर्ग अभिभावक वर्ग की आभासी पद्धति को ओवरराइड कर सकते हैं।

सार विधियां

सभी संगठनों को अच्छी तरह से ड्रिल नहीं किया जाता है। कुछ संगठन फायर ड्रिल नहीं करते हैं। उनके पास समग्र भागने की नीति नहीं है। हर आदमी अपने लिए है। प्रबंधन केवल इस तरह की नीति में रुचि रखते हैं।

दूसरे शब्दों में, प्रत्येक व्यक्ति को अपनी खुद की FireEscape () विधि विकसित करने के लिए मजबूर किया जाता है। एक आदमी आग से बचकर निकल जाएगा। एक और आदमी पैराशूट करेगा। एक अन्य व्यक्ति इमारत से दूर उड़ान भरने के लिए रॉकेट प्रोपल्शन तकनीक का उपयोग करेगा। एक और आदमी बाहर छोड़ देगा। प्रबंधन परवाह नहीं करता है कि आप कैसे बच निकलते हैं, इसलिए जब तक आपके पास एक बेसिक फायरएस्केप () योजना है - अगर उन्हें गारंटी नहीं दी जाती है कि ओएचएस ईंटों के एक टन की तरह संगठन पर नीचे आ जाएगा। यह एक अमूर्त विधि से अभिप्राय है।

दोनों में फिर क्या अंतर है?

सार विधि: उप-वर्गों को अपने फायरइस्केप विधि को लागू करने के लिए मजबूर किया जाता है। एक आभासी विधि के साथ, आपके पास एक मूल योजना है जो आपके लिए इंतजार कर रही है, लेकिन यदि यह पर्याप्त रूप से अच्छा नहीं है, तो इसे लागू करने का विकल्प चुन सकते हैं ।

अब यह इतना कठिन नहीं था?


22

एक अमूर्त विधि एक विधि है जिसे एक ठोस वर्ग बनाने के लिए लागू किया जाना चाहिए। घोषणा सार वर्ग में है (और अमूर्त विधि के साथ किसी भी वर्ग को एक सार वर्ग होना चाहिए) और इसे एक ठोस कक्षा में लागू किया जाना चाहिए।

एक आभासी विधि एक ऐसी विधि है जिसे सुपरक्लास में व्यवहार की जगह , ओवरराइड का उपयोग करके एक व्युत्पन्न वर्ग में ओवरराइड किया जा सकता है । यदि आप ओवरराइड नहीं करते हैं, तो आपको मूल व्यवहार मिलता है। यदि आप करते हैं, तो आपको हमेशा नया व्यवहार मिलता है। यह आभासी तरीकों का विरोध नहीं करता है, जिन्हें ओवरराइड नहीं किया जा सकता है लेकिन मूल विधि को छिपा सकते हैं। यह newसंशोधक का उपयोग करके किया जाता है ।

निम्नलिखित उदाहरण देखें:

public class BaseClass
{
    public void SayHello()
    {
        Console.WriteLine("Hello");
    }


    public virtual void SayGoodbye()
    {
        Console.WriteLine("Goodbye");
    }

    public void HelloGoodbye()
    {
        this.SayHello();
        this.SayGoodbye();
    }
}


public class DerivedClass : BaseClass
{
    public new void SayHello()
    {
        Console.WriteLine("Hi There");
    }


    public override void SayGoodbye()
    {
        Console.WriteLine("See you later");
    }
}

जब मैं त्वरित DerivedClassऔर कॉल करता हूं SayHello, या SayGoodbye, मुझे "हाय वहाँ" और "बाद में मिलते हैं" मिलता है। यदि मैं फोन करता हूं HelloGoodbye, तो मुझे "हैलो" और "बाद में मिलते हैं" मिलता है। ऐसा इसलिए है क्योंकि SayGoodbyeयह आभासी है, और इसे व्युत्पन्न वर्गों द्वारा प्रतिस्थापित किया जा सकता है। SayHelloकेवल छिपा हुआ है, इसलिए जब मैं कहता हूं कि मेरे आधार वर्ग से मुझे मेरी मूल विधि मिलती है।

सार विधियां आभासी रूप से निहित हैं। वे उस व्यवहार को परिभाषित करते हैं जो मौजूद होना चाहिए, एक इंटरफ़ेस की तरह।


9

सार विधियां हमेशा आभासी होती हैं। उनका कार्यान्वयन नहीं हो सकता।

यही मुख्य अंतर है।

मूल रूप से, आप एक आभासी पद्धति का उपयोग करेंगे यदि आपके पास इसका 'डिफ़ॉल्ट' कार्यान्वयन है और वंशजों को इसके व्यवहार को बदलने की अनुमति देना चाहते हैं।

एक अमूर्त विधि के साथ, आप वंशजों को एक कार्यान्वयन प्रदान करने के लिए मजबूर करते हैं।


9

मैंने निम्नलिखित कक्षाओं में (अन्य उत्तरों से) कुछ सुधार करके इसे सरल बनाया है:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestOO
{
    class Program
    {
        static void Main(string[] args)
        {
            BaseClass _base = new BaseClass();
            Console.WriteLine("Calling virtual method directly");
            _base.SayHello();
            Console.WriteLine("Calling single method directly");
            _base.SayGoodbye();

            DerivedClass _derived = new DerivedClass();
            Console.WriteLine("Calling new method from derived class");
            _derived.SayHello();
            Console.WriteLine("Calling overrided method from derived class");
            _derived.SayGoodbye();

            DerivedClass2 _derived2 = new DerivedClass2();
            Console.WriteLine("Calling new method from derived2 class");
            _derived2.SayHello();
            Console.WriteLine("Calling overrided method from derived2 class");
            _derived2.SayGoodbye();
            Console.ReadLine();
        }
    }


    public class BaseClass
    {
        public void SayHello()
        {
            Console.WriteLine("Hello\n");
        }
        public virtual void SayGoodbye()
        {
            Console.WriteLine("Goodbye\n");
        }

        public void HelloGoodbye()
        {
            this.SayHello();
            this.SayGoodbye();
        }
    }


    public abstract class AbstractClass
    {
        public void SayHello()
        {
            Console.WriteLine("Hello\n");
        }


        //public virtual void SayGoodbye()
        //{
        //    Console.WriteLine("Goodbye\n");
        //}
        public abstract void SayGoodbye();
    }


    public class DerivedClass : BaseClass
    {
        public new void SayHello()
        {
            Console.WriteLine("Hi There");
        }

        public override void SayGoodbye()
        {
            Console.WriteLine("See you later");
        }
    }

    public class DerivedClass2 : AbstractClass
    {
        public new void SayHello()
        {
            Console.WriteLine("Hi There");
        }
        // We should use the override keyword with abstract types
        //public new void SayGoodbye()
        //{
        //    Console.WriteLine("See you later2");
        //}
        public override void SayGoodbye()
        {
            Console.WriteLine("See you later");
        }
    }
}

6

बाइंडिंग कोड की एक इकाई के लिए एक नाम मैप करने की प्रक्रिया है।

देर से बाँधना अर्थ है कि हम नाम का उपयोग करते हैं, लेकिन मैपिंग को स्थगित कर देते हैं। दूसरे शब्दों में, हम पहले नाम का निर्माण / उल्लेख करते हैं, और कुछ बाद की प्रक्रिया को उस नाम के लिए कोड की मैपिंग को संभालने देते हैं।

अब विचार करें:

  • मनुष्यों की तुलना में, मशीनें वास्तव में खोज और छंटाई में अच्छी हैं
  • मशीनों की तुलना में, मनुष्य वास्तव में आविष्कार और नवाचार में अच्छे हैं

तो, संक्षिप्त उत्तर है: virtualमशीन (रनटाइम) के लिए एक देर से बाध्यकारी निर्देश हैabstract लिए देर से बाध्यकारी निर्देश है मानव (प्रोग्रामर) के लिए देर से बाध्यकारी निर्देश है

दूसरे शब्दों में, virtualइसका मतलब है:

"प्रिय रनटाइम , इस कोड को इस नाम से बाँध कर वही करें जो आप सबसे अच्छा करते हैं: खोज "

जबकि abstractइसका मतलब है:

"प्रिय प्रोग्रामर , कृपया इस नाम के लिए उपयुक्त कोड को वही करें जो आप सबसे अच्छा करते हैं: आविष्कार करना "

संपूर्णता के लिए, अतिभार का मतलब है:

"प्रिय संकलक , इस नाम के लिए उपयुक्त कोड को वही करें जो आप सबसे अच्छा करते हैं: छँटाई ।"


3

आप मूल रूप से एक वर्चुअल विधि का उपयोग करते हैं जब आप चाहते हैं कि इनहेरिटर्स कार्यक्षमता का विस्तार करें यदि वे चाहते हैं।

जब आप इनहेरिटर्स को कार्यक्षमता को लागू करना चाहते हैं (और इस मामले में उनके पास कोई विकल्प नहीं है) तो आप अमूर्त विधियों का उपयोग करते हैं


3

आभासी विधि :

  • वर्चुअल का मतलब है कि हम इसे ओवरराइड कर सकते हैं।

  • वर्चुअल फंक्शन का कार्यान्वयन है। जब हमें कक्षा विरासत में मिलती है तो हम आभासी फ़ंक्शन को ओवरराइड कर सकते हैं और अपना तर्क प्रदान कर सकते हैं।

  • हम
    चाइल्ड क्लास (जिसे
    शैडोइंग की अवधारणा के रूप में कहा जा सकता है ) में फ़ंक्शन को लागू करते समय रिटर्न प्रकार के वर्चुअल फ़ंक्शन को बदल सकते हैं ।

सार विधि

  • सार का मतलब है कि हम इसे ओवरराइड करेंगे।

  • एक सार फ़ंक्शन का कोई कार्यान्वयन नहीं है और एक सार वर्ग में होना चाहिए।

  • इसे केवल घोषित किया जा सकता है। यह व्युत्पन्न वर्ग को इसे लागू करने के लिए बाध्य करता है।

  • एक अमूर्त सदस्य अंतर्निहित आभासी है। अमूर्त को कुछ भाषाओं में शुद्ध आभासी कहा जा सकता है।

    public abstract class BaseClass
    { 
        protected abstract void xAbstractMethod();
    
        public virtual void xVirtualMethod()
        {
            var x = 3 + 4;
        }
    } 
    

2

मैंने कुछ स्थानों पर देखा है कि अमूर्त विधि नीचे के रूप में परिभाषित की गई है। **

"एब्सट्रैक्ट मेथड को चाइल्ड क्लास में लागू करना होगा"

** मुझे लगा कि यह जैसा है।

यह आवश्यक नहीं है कि एक अमूर्त पद्धति को बाल वर्ग में लागू किया जाना चाहिए, यदि बाल वर्ग भी सार है

1) एक सार विधि एक निजी विधि नहीं हो सकती। 2) एक सार विधि कठबोली को एक ही अमूर्त वर्ग में लागू किया जा सकता है।

मैं कहूंगा .. यदि हम एक सार वर्ग को लागू कर रहे हैं, तो आपको आधार सार वर्ग से सार विधियों को ओवरराइड करना होगा। क्योंकि .. अमूर्त विधि को लागू करना कुंजी शब्द को ओवरराइड करने के लिए है। वर्चुअल विधि के लिए।

विरासत में मिली कक्षा में वर्चुअल विधि को लागू करना आवश्यक नहीं है।

                                 ----------CODE--------------

public abstract class BaseClass
{
    public int MyProperty { get; set; }
    protected abstract void MyAbstractMethod();

    public virtual void MyVirtualMethod()
    {
        var x = 3 + 4;
    }

}
public abstract class myClassA : BaseClass
{
    public int MyProperty { get; set; }
    //not necessary to implement an abstract method if the child class is also abstract.

    protected override void MyAbstractMethod()
    {
        throw new NotImplementedException();
    }
}
public class myClassB : BaseClass
{
    public int MyProperty { get; set; }
    //You must have to implement the abstract method since this class is not an abstract class.

    protected override void MyAbstractMethod()
    {
        throw new NotImplementedException();
    }
}

2

उपर्युक्त अधिकांश उदाहरण कोड का उपयोग करते हैं - और वे बहुत अच्छे हैं। मुझे उनके बताए अनुसार जोड़ने की आवश्यकता नहीं है, लेकिन निम्नलिखित एक सरल स्पष्टीकरण है जो कोड / तकनीकी शब्दों के बजाय एनालॉग का उपयोग करता है।

सरल व्याख्या - उपमाओं का उपयोग करते हुए स्पष्टीकरण

सार विधि

जॉर्ज डब्ल्यू बुश सोचो। वह अपने सैनिकों से कहता है: "इराक में लड़ाई जाओ"। और बस। उन्होंने कहा कि लड़ाई पूरी होनी चाहिए। वह निर्दिष्ट नहीं करता है कि वास्तव में ऐसा कैसे होगा। लेकिन मेरा मतलब है, आप अभी बाहर नहीं जा सकते हैं और "लड़ाई": इसका क्या मतलब है? क्या मैं बी -52 या मेरे डेरिंगर से लड़ता हूँ? उन विशिष्ट विवरणों को किसी और को छोड़ दिया जाता है। यह एक अमूर्त विधि है।

आभासी विधि

डेविड पेट्रायस सेना में उच्च है। उन्होंने परिभाषित किया है कि लड़ाई का क्या मतलब है:

  1. दुश्मन को खोजो
  2. उसे बेअसर।
  3. बाद में एक बीयर लें

समस्या यह है कि यह एक बहुत ही सामान्य तरीका है। यह एक अच्छा तरीका है जो काम करता है, लेकिन कभी-कभी यह विशिष्ट नहीं होता है। पेट्रिएस के लिए अच्छी बात यह है कि उनके आदेशों में बदलाव और गुंजाइश है - उन्होंने दूसरों को "लड़ाई" की परिभाषा को अपनी विशेष आवश्यकताओं के अनुसार बदलने की अनुमति दी है।

निजी नौकरी ब्लॉग्स ने पेट्राईस के आदेश को पढ़ा और उसे अपनी विशेष आवश्यकताओं के अनुसार, लड़ाई के अपने संस्करण को लागू करने की अनुमति दी गई:

  1. शत्रु का पता लगाएं।
  2. उसे सिर में गोली मारो।
  3. घर जाओ
  4. बियर लो।

नूरी अल मलिकी को भी पेट्रिएस से ऐसे ही आदेश मिले। उसे भी लड़ना है। लेकिन वह एक राजनेता हैं, पैदल सेना के आदमी नहीं। जाहिर है कि वह अपने राजनीतिक दुश्मनों को सिर में गोली मारने के आसपास नहीं जा सकते। क्योंकि पेट्रिएस ने उसे एक आभासी तरीका दिया है, तो मालिकी अपनी विशेष परिस्थितियों के अनुसार, लड़ाई विधि के अपने संस्करण को लागू कर सकती है:

  1. शत्रु का पता लगाएं।
  2. क्या उन्होंने कुछ बीएस को आरोपों के साथ गिरफ्तार किया है।
  3. घर जाओ
  4. बियर लो।

दूसरे शब्दों में, एक आभासी विधि बॉयलरप्लेट निर्देश प्रदान करती है - लेकिन ये सामान्य निर्देश हैं, जिन्हें सेना के उत्तराधिकारियों द्वारा लोगों द्वारा उनकी विशेष परिस्थितियों के अनुसार अधिक विशिष्ट बनाया जा सकता है।

दोनों में अंतर

  • जॉर्ज बुश किसी भी कार्यान्वयन विवरण को साबित नहीं करते हैं। यह किसी और द्वारा प्रदान किया जाना चाहिए। यह एक अमूर्त विधि है।

  • दूसरी तरफ पेट्रिएस कार्यान्वयन विवरण प्रदान करता है लेकिन उसने अपने अधीनस्थों को अपने स्वयं के संस्करण के साथ अपने आदेशों को ओवरराइड करने की अनुमति दी है, अगर वे कुछ बेहतर कर सकते हैं।

उम्मीद है की वो मदद करदे।


2

सार फ़ंक्शन (विधि):

● एक अमूर्त विधि एक विधि है जिसे कीवर्ड सार के साथ घोषित किया जाता है।

● इसमें शरीर नहीं है।

● इसे व्युत्पन्न वर्ग द्वारा लागू किया जाना चाहिए।

● यदि कोई विधि अमूर्त है तो कक्षा को अमूर्त करना चाहिए।

आभासी फ़ंक्शन (विधि):

● एक वर्चुअल विधि वह विधि है जिसे कीवर्ड वर्चुअल के साथ घोषित किया जाता है और इसे ओवरराइड कीवर्ड का उपयोग करके व्युत्पन्न वर्ग विधि द्वारा ओवरराइड किया जा सकता है।

● यह व्युत्पन्न वर्ग के ऊपर है कि इसे ओवरराइड किया जाए या नहीं।


1

उत्तर कई बार प्रदान किया गया है, लेकिन सवाल यह है कि प्रत्येक का उपयोग कब किया जाए, यह एक डिज़ाइन-टाइम निर्णय है। मैं सामान्य पद्धति परिभाषाओं को अलग-अलग इंटरफेस में बाँधने और उन्हें उपयुक्त अमूर्त स्तरों पर कक्षाओं में खींचने के लिए अच्छे अभ्यास के रूप में देखूंगा। एक वर्ग में अमूर्त और आभासी विधि परिभाषाओं के एक सामान्य सेट को डंप करना वर्ग को अप्रस्तुत करता है जब एक गैर-अमूर्त वर्ग को परिभाषित करना सबसे अच्छा हो सकता है जो संक्षिप्त इंटरफेस के एक सेट को लागू करता है। हमेशा की तरह, यह इस बात पर निर्भर करता है कि आपके एप्लिकेशन विशिष्ट आवश्यकताओं के लिए सबसे उपयुक्त हैं।


1

सार क्रिया बॉडी नहीं हो सकती है और चाइल्ड क्लासेस को ओवरस्ट्रीम होना चाहिए

वर्चुअल फंक्शन में एक बॉडी होगी और चाइल्ड क्लासेस द्वारा ओवरराइड की जा सकती है या नहीं


1

सामान्य वस्तु उन्मुख दृष्टिकोण से:

अमूर्त विधि के बारे में : जब आप मूल कक्षा में एक अमूर्त विधि डालते हैं तो वास्तव में आपके बच्चे कक्षाओं से कह रहे हैं: अरे ध्यान दें कि आपके पास इस तरह से एक विधि हस्ताक्षर है। और अगर आप इसका उपयोग करना चाहते हैं तो आपको अपना खुद का कार्यान्वयन करना चाहिए!

वर्चुअल फंक्शन के बारे में : जब आप अभिभावक वर्ग को एक वर्चुअल तरीका बताते हैं, जो आप व्युत्पन्न कक्षाओं से कह रहे हैं: अरे यहाँ एक कार्यक्षमता है जो आपके लिए कुछ करती है। यदि यह आपके लिए उपयोगी है तो बस इसका उपयोग करें। यदि नहीं, तो इसे ओवरराइड करें और अपना कोड लागू करें, यहां तक ​​कि आप अपने कोड में मेरे कार्यान्वयन का उपयोग कर सकते हैं!

यह जनरल ओओ में इस दो अवधारणा के बीच भिन्न के बारे में कुछ दर्शन है


1

एक अमूर्त फ़ंक्शन एक कार्यान्वयन के बिना "बस" एक हस्ताक्षर है। इसका उपयोग इंटरफ़ेस में यह घोषित करने के लिए किया जाता है कि कक्षा का उपयोग कैसे किया जा सकता है। इसे व्युत्पन्न वर्गों में से एक में लागू किया जाना चाहिए।

वर्चुअल फ़ंक्शन (विधि वास्तव में), एक फ़ंक्शन है जिसे आप भी घोषित करते हैं, और विरासत वंशानुक्रम वर्गों में से एक में लागू किया जाना चाहिए।

इस तरह के वर्ग के विरासत वाले उदाहरण, कार्यान्वयन को भी विरासत में लेते हैं, जब तक कि आप इसे लागू नहीं करते हैं, निम्न श्रेणी के वर्ग में।


0

C # में वर्चुअल क्लास कुछ भी नहीं हैं।

कार्यों के लिए

  1. सार फ़ंक्शन में केवल हस्ताक्षर हैं, ड्राइव क्लास को कार्यक्षमता के साथ ओवरराइड करना चाहिए।
  2. वर्चुअल फ़ंक्शन कार्यक्षमता के भाग को धारण करेगा, ड्राइव क्लास आवश्यकता के अनुसार इसे ओवरराइड कर सकता है या नहीं कर सकता है

आप अपनी आवश्यकता के साथ तय कर सकते हैं।


0

अमूर्त विधि में एक कार्यान्वयन नहीं है। यह मूल वर्ग में घोषित किया गया है। उस पद्धति को लागू करने के लिए बाल वर्ग प्रतिक्रियाशील है।

वर्चुअल मेथड का पैरेंट क्लास में इंप्लीमेंटेशन होना चाहिए और यह चाइल्ड क्लास को यह पसंद करने की सुविधा देता है कि पेरेंट क्लास के उस इम्प्लीमेंटेशन का उपयोग करना है या चाइल्ड क्लास में उस तरीके के लिए खुद के लिए नया इम्प्लीमेंटेशन करना है।


0

C ++ बैकग्राउंड से, C # वर्चुअल, C ++ वर्चुअल से मेल खाता है, जबकि C # एब्स्ट्रैक्ट मेथड C ++ वर्चुअल फंक्शन से मेल खाता है


0

अमूर्त कार्य या विधि एक सार्वजनिक "ऑपरेशन का नाम" है जिसे एक वर्ग द्वारा उजागर किया गया है, इसका उद्देश्य, अमूर्त कक्षाओं के साथ, मुख्य रूप से संरचना के खिलाफ वस्तुओं के डिजाइन में एक बाधा का एक रूप प्रदान करता है जिसे किसी वस्तु को लागू करना है।

वास्तव में, अपने अमूर्त वर्ग से विरासत में मिली कक्षाओं को इस पद्धति को एक कार्यान्वयन देना होता है, आम तौर पर कंपाइलर त्रुटियों को उठाते हैं जब वे नहीं करते हैं।

अमूर्त कक्षाओं और विधियों का उपयोग करना ज्यादातर महत्वपूर्ण है कि कक्षाओं को डिजाइन करते समय कार्यान्वयन विवरणों पर ध्यान केंद्रित करने से, कक्षाओं की संरचना भी कार्यान्वयन से संबंधित होती है, इसलिए उन वर्गों के बीच निर्भरता और युग्मन पैदा करना जो उनके बीच सहयोग करते हैं।

एक आभासी फ़ंक्शन या विधि बस एक विधि है जो एक वर्ग के सार्वजनिक व्यवहार को मॉडल करती है, लेकिन हम इसे विरासत श्रृंखला में संशोधित करने के लिए स्वतंत्र छोड़ सकते हैं, क्योंकि हमें लगता है कि बाल वर्गों को उस व्यवहार के लिए कुछ विशिष्ट एक्सटेंशन को लागू करने की आवश्यकता हो सकती है।

वे दोनों वस्तु अभिविन्यास प्रतिमान में बहुरूपता के एक रूप का प्रतिनिधित्व करते हैं ।

हम एक अच्छा वंशानुक्रम मॉडल का समर्थन करने के लिए एक साथ सार विधियों और आभासी कार्यों का उपयोग कर सकते हैं।

हम अपने समाधान की मुख्य वस्तुओं की एक अच्छी सार संरचना तैयार करते हैं, फिर आगे की विशेषज्ञता के लिए उन अधिक संभावना का पता लगाकर बुनियादी कार्यान्वयन बनाते हैं और हम इन लोगों को आभासी के रूप में बनाते हैं, अंत में हम अपने बुनियादी कार्यान्वयन को व्यवस्थित करते हैं, अंतत: आभासी लोगों को "ओवरराइडिंग" करते हैं।


0

यहाँ मैं कुछ नमूना कोड लिख रहा हूँ जिससे यह उम्मीद की जा सकती है कि यह बहुत ही बुनियादी स्तर पर इंटरफेस, अमूर्त वर्ग और साधारण कक्षाओं के व्यवहार को देखने के लिए एक बहुत ही ठोस उदाहरण हो सकता है। यदि आप इसे एक डेमो के रूप में उपयोग करना चाहते हैं, तो आप इस कोड को एक प्रोजेक्ट के रूप में भी पा सकते हैं: https://github.com/usavas/JavaAbstractAndInterfaceDemo

public interface ExampleInterface {

//    public void MethodBodyInInterfaceNotPossible(){
//    }
    void MethodInInterface();

}

public abstract class AbstractClass {
    public abstract void AbstractMethod();

    //    public abstract void AbstractMethodWithBodyNotPossible(){
    //
    //    };

    //Standard Method CAN be declared in AbstractClass
    public void StandardMethod(){
        System.out.println("Standard Method in AbstractClass (super) runs");
    }
}

public class ConcreteClass
    extends AbstractClass
    implements ExampleInterface{

    //Abstract Method HAS TO be IMPLEMENTED in child class. Implemented by ConcreteClass
    @Override
    public void AbstractMethod() {
        System.out.println("AbstractMethod overridden runs");
    }

    //Standard Method CAN be OVERRIDDEN.
    @Override
    public void StandardMethod() {
        super.StandardMethod();
        System.out.println("StandardMethod overridden in ConcreteClass runs");
    }

    public void ConcreteMethod(){
        System.out.println("Concrete method runs");
    }

    //A method in interface HAS TO be IMPLEMENTED in implementer class.
    @Override
    public void MethodInInterface() {
        System.out.println("MethodInInterface Implemented by ConcreteClass runs");

    //    Cannot declare abstract method in a concrete class
    //    public abstract void AbstractMethodDeclarationInConcreteClassNotPossible(){
    //
    //    }
    }
}

0

यदि कोई वर्ग इस अमूर्त वर्ग से निकलता है, तो उसे अमूर्त सदस्य को ओवरराइड करने के लिए मजबूर किया जाता है। यह आभासी संशोधक से अलग है, जो निर्दिष्ट करता है कि सदस्य वैकल्पिक रूप से ओवरराइड कर सकता है।


-4

मेरी समझ में:

सार तरीके:

केवल अमूर्त वर्ग ही सार विधियों को धारण कर सकता है। इसके अलावा, व्युत्पन्न वर्ग को विधि को लागू करने की आवश्यकता है और कक्षा में कोई कार्यान्वयन प्रदान नहीं किया गया है।

वर्चुअल तरीके:

एक वर्ग इन्हें घोषित कर सकता है और इन्हें लागू करने की व्यवस्था भी कर सकता है। इसके अलावा व्युत्पन्न वर्ग को इसे ओवरराइड करने की विधि को लागू करने की आवश्यकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.