c# - एक अमूर्त कार्य और वर्चुअल फ़ंक्शन के बीच क्या अंतर है?




oop programming-languages (14)

एक अमूर्त कार्य और वर्चुअल फ़ंक्शन के बीच क्या अंतर है? वर्चुअल या अमूर्त का उपयोग करने के लिए किस मामले में सिफारिश की जाती है? कौन सा सही दृष्टिकोण है?


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

आपको हमेशा एक अमूर्त फ़ंक्शन को ओवरराइड करना होगा।

इस प्रकार:

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

एक अमूर्त कार्य में कोई कार्यान्वयन नहीं होता है और इसे केवल एक अमूर्त वर्ग पर ही घोषित किया जा सकता है। यह व्युत्पन्न वर्ग को कार्यान्वयन प्रदान करने के लिए मजबूर करता है। एक वर्चुअल फ़ंक्शन एक डिफ़ॉल्ट कार्यान्वयन प्रदान करता है और यह या तो एक सार वर्ग या गैर-सारणी वर्ग पर मौजूद हो सकता है। तो उदाहरण के लिए:

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();
}

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

वर्चुअल विधि एक विधि है जिसे ओवरराइड का उपयोग करके व्युत्पन्न कक्षा में ओवरराइड किया जा सकता है, सुपरक्लास में व्यवहार को बदलना । यदि आप ओवरराइड नहीं करते हैं, तो आपको मूल व्यवहार मिलता है। यदि आप करते हैं, तो आपको हमेशा नया व्यवहार मिलता है। यह वर्चुअल विधियों का विरोध नहीं करता है, जिसे ओवरराइड नहीं किया जा सकता है लेकिन मूल विधि को छुपा सकता है। यह 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 चालू करता DerivedClass और SayHello , या SayGoodbye कॉल SayHello SayGoodbye , तो मुझे "हाय वहाँ" मिलता है और "बाद में मिलते हैं"। अगर मैं HelloGoodbye कॉल करता HelloGoodbye , तो मुझे "हैलो" मिलता है और "बाद में मिलते हैं"। ऐसा इसलिए है क्योंकि SayGoodbye आभासी है, और व्युत्पन्न कक्षाओं द्वारा प्रतिस्थापित किया जा सकता है। SayHello केवल छुपा हुआ है, इसलिए जब मैं इसे अपनी बेस क्लास से कॉल करता हूं तो मुझे अपनी मूल विधि मिलती है।

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


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


मेरी समझ के लिए:

सार विधि:

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

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

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


मैंने निम्नलिखित वर्गों (अन्य उत्तरों से) में कुछ सुधार करके यह आसान बना दिया है:

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");
        }
    }
}

सामान्य वस्तु उन्मुख दृश्य से:

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

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

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


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

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

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

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


सार समारोह (विधि):

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

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

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

● यदि कोई विधि सार है तो वर्ग को सार होना चाहिए।

वर्चुअल फ़ंक्शन (विधि):

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

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


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

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

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

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


स्पष्टीकरण: अनुरूपता के साथ। उम्मीद है कि यह आपकी मदद करेगा।

प्रसंग

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

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

  1. सामान इकट्ठा मत करो
  2. भागने के लिए चलो
  3. इमारत से बाहर चले जाओ

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

वर्चुअल विधि

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

  1. खिड़की पर चलाएं
  2. खिड़की से बाहर निकलें
  3. नीचे से पैराशूट सुरक्षित रूप से

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

सार तरीकों

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

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

दो के बीच क्या अंतर है?

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

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


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

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

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

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

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

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

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

जबकि abstract साधन हैं:

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

पूर्णता के लिए, ओवरलोडिंग का अर्थ है:

"प्रिय कंपाइलर , जो भी आप सबसे अच्छा करते हैं, उसके द्वारा उपयुक्त कोड को बाध्य करें: सॉर्टिंग "।


वर्चुअल विधि :

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

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

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

सार विधि

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

  • एक अमूर्त कार्य में कोई कार्यान्वयन नहीं होता है और एक अमूर्त वर्ग में होना चाहिए।

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

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

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




abstract