मैं विज़ुअल स्टूडियो 2008 विंडोज फॉर्म डिजाइनर कैसे प्राप्त कर सकता हूं जो एक फॉर्म को प्रस्तुत करने के लिए एक अमूर्त आधार वर्ग को लागू करता है?


98

मैंने विंडोज फॉर्म में विरासत में मिले नियंत्रणों के साथ एक समस्या को जोड़ा और उस पर कुछ सलाह की आवश्यकता थी।

मैं सूची में आइटमों के लिए एक आधार वर्ग का उपयोग करता हूं (एक पैनल से बनी सेल्फमेड जीयूआई सूची) और कुछ विरासत में मिले नियंत्रण जो प्रत्येक प्रकार के डेटा के लिए हैं जिन्हें सूची में जोड़ा जा सकता है।

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

जब मैं बेस-कंट्रोल को सार के रूप में चिह्नित करता हूं, तो विज़ुअल स्टूडियो 2008 डिज़ाइनर खिड़की को लोड करने से इनकार करता है।

क्या बेस-कंट्रोल एब्सट्रैक्ट के साथ डिजाइनर का काम पाने का कोई तरीका है?

जवाबों:


97

I KNEW को ऐसा करने का एक तरीका होना चाहिए था (और मुझे यह सफाई से करने का एक तरीका मिला)। शेंग का समाधान वास्तव में वही है जो मैं एक अस्थायी वर्कअराउंड के रूप में आया था, लेकिन एक दोस्त ने बताया कि Formक्लास अंत में ए से विरासत में मिलीabstract , हम इसे पूरा करने में सक्षम होंगे। अगर वे ऐसा कर सकते हैं, तो हम कर सकते हैं।

हम इस कोड से समस्या के लिए गए थे

Form1 : Form

संकट

public class Form1 : BaseForm
...
public abstract class BaseForm : Form

यह वह जगह है जहाँ प्रारंभिक प्रश्न खेल में आया था। जैसा कि पहले कहा गया था, एक मित्र ने बताया कि System.Windows.Forms.Formएक आधार वर्ग है जो अमूर्त है। हम खोजने में सक्षम थे ...

बेहतर समाधान का प्रमाण

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

प्रारंभिक समाधान

public class Form1 : MiddleClass
...
public class MiddleClass : BaseForm
... 
public abstract class BaseForm : Form
... 

यह वास्तव में काम करता है और डिजाइनर इसे ठीक करता है, समस्या हल करता है .... सिवाय आपके आपके उत्पादन अनुप्रयोग में विरासत के एक अतिरिक्त स्तर के जो केवल winforms डिजाइनर में एक अपर्याप्तता के कारण आवश्यक था!

यह एक 100% अचूक समाधान नहीं है, लेकिन यह बहुत अच्छा है। मूल रूप से आप #if DEBUGपरिष्कृत समाधान के साथ आने के लिए उपयोग करते हैं।

परिष्कृत समाधान

Form1.cs

#if DEBUG
public class Form1 : MiddleClass
#else 
public class Form1 : BaseForm
#endif
...

MiddleClass.cs

public class MiddleClass : BaseForm
... 

BaseForm.cs

public abstract class BaseForm : Form
... 

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

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

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


3
क्या आपका फॉर्म और एब्सट्रैक्ट बेस क्लास में नो-आर्ग कंस्ट्रक्टर है? कारण यह है कि हम सभी को डिजाइनर को काम करने के लिए जोड़ना था, जो एक सार रूप से विरासत में मिला।
ओपन स्कूल

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

1
आपका समाधान महान काम करता है। मैं बस विश्वास नहीं कर सकता कि दृश्य स्टूडियो को कुछ सामान्य करने के लिए इस तरह के हुप्स के माध्यम से कूदने की आवश्यकता होती है।
आरबी डेविडसन

1
लेकिन अगर मैं एक मिडलक्लास का उपयोग करता हूं, जो कि एब्सट्रैक्ट क्लास नहीं है, तो जो भी मिडलक्लास को विरासत में मिला है, उसे एब्सट्रैक्ट मेथड लागू नहीं करना है, यह पहली जगह में एब्सट्रैक्ट क्लास को इस्तेमाल करने के बहुत उद्देश्य को मात देता है ... इसे कैसे हल करें?
डेरियस

1
@ ti034 मुझे कोई वर्कअराउंड नहीं मिला। इसलिए मैं सिर्फ बीच के कार्यों को कथित रूप से अमूर्त बनाता हूं। कुछ डिफ़ॉल्ट मान हैं जो मुझे आसानी से उन्हें ओवरराइड करने के लिए याद दिला सकते हैं, बिना कंपाइलर को त्रुटि फेंकने के लिए। उदाहरण के लिए, यदि माना जाता है कि अमूर्त विधि पृष्ठ का शीर्षक वापस करना है, तो मैं इसे एक स्ट्रिंग "कृपया शीर्षक बदलें" कर देगा।
डेरियस

74

@smelch, डिबग के लिए भी, एक मध्य नियंत्रण बनाने के बिना, एक बेहतर समाधान है।

हमें क्या चाहिऐ

पहले, चलो अंतिम वर्ग और आधार सार वर्ग को परिभाषित करते हैं।

public class MyControl : AbstractControl
...
public abstract class AbstractControl : UserControl // Also works for Form
...

अब हम सभी की जरूरत है एक विवरण प्रदाता है

public class AbstractControlDescriptionProvider<TAbstract, TBase> : TypeDescriptionProvider
{
    public AbstractControlDescriptionProvider()
        : base(TypeDescriptor.GetProvider(typeof(TAbstract)))
    {
    }

    public override Type GetReflectionType(Type objectType, object instance)
    {
        if (objectType == typeof(TAbstract))
            return typeof(TBase);

        return base.GetReflectionType(objectType, instance);
    }

    public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
    {
        if (objectType == typeof(TAbstract))
            objectType = typeof(TBase);

        return base.CreateInstance(provider, objectType, argTypes, args);
    }
}

अंत में हम केवल टाइपस्ट्रेपप्रॉइडर एब्स्ट्रैक्ट कंट्रोल पर लागू करते हैं।

[TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider<AbstractControl, UserControl>))]
public abstract class AbstractControl : UserControl
...

और बस। कोई मध्य नियंत्रण की आवश्यकता नहीं है।

और प्रदाता वर्ग को कई सार आधारों पर लागू किया जा सकता है जैसा कि हम एक ही समाधान में चाहते हैं।

* EDIT * इसके अलावा app.config में निम्नलिखित की जरूरत है

<appSettings>
    <add key="EnableOptimizedDesignerReloading" value="false" />
</appSettings>

सुझाव के लिए @ user3057544 धन्यवाद।



1
यह मेरे लिए भी काम करता है कि मैं CF 3.5 का उपयोग कर रहा TypeDescriptionProvider
हूं

4
यह वीएस 2010 में काम करने के लिए नहीं मिला, हालांकि स्मेलच ने काम किया। किसी को पता है क्यों?
RobC

5
@RobC डिज़ाइनर किसी कारणवश क्रोधी है। मैंने पाया कि इस फिक्स को लागू करने के बाद मुझे समाधान को बंद करना पड़ा और VS2010 को फिर से लॉन्च किया, और पुनर्निर्माण किया; तो यह मुझे उपवर्ग डिजाइन करने देगा।
आज्ञाकारी साधु

3
यह ध्यान देने योग्य है क्योंकि यह फिक्स सार वर्ग के लिए बेस क्लास का एक उदाहरण स्थानापन्न करता है , उपवर्गों को डिज़ाइन करते समय अमूर्त वर्ग के लिए डिज़ाइनर में जोड़े गए दृश्य तत्व उपलब्ध नहीं होंगे।
आज्ञाकारी ऋषि

1
यह मेरे लिए काम करता है, लेकिन मुझे प्रोजेक्ट बनाने के बाद सबसे पहले वीएस 2013 को फिर से शुरू करना पड़ा। @ObliviousSage - हेड-अप के लिए धन्यवाद; मेरे वर्तमान मामले में कम से कम यह एक मुद्दा नहीं है, लेकिन फिर भी यह देखने के लिए अच्छा है।
InteXX

10

@Smelch, उपयोगी उत्तर के लिए धन्यवाद, जैसा कि मैं हाल ही में उसी मुद्दे पर चल रहा था।

संकलन चेतावनियों को रोकने के लिए ( #if DEBUGपूर्व-प्रोसेसर निर्देश के भीतर आधार वर्ग डालकर) आपकी पोस्ट के लिए एक छोटा बदलाव किया जा रहा है :

public class Form1
#if DEBUG  
 : MiddleClass 
#else  
 : BaseForm 
#endif 

5

मुझे एक समान समस्या थी लेकिन एक सार आधार वर्ग के स्थान पर एक इंटरफ़ेस का उपयोग करने के लिए चीजों को रिफलेक्टर करने का एक तरीका मिला:

interface Base {....}

public class MyUserControl<T> : UserControl, Base
     where T : /constraint/
{ ... }

यह हर स्थिति पर लागू नहीं हो सकता है, लेकिन जब संभव हो तो सशर्त संकलन की तुलना में एक क्लीनर समाधान में परिणाम होता है।


1
क्या आप थोड़ा और पूर्ण कोड नमूना प्रदान कर सकते हैं? मैं आपके डिज़ाइन को बेहतर तरीके से समझने की कोशिश कर रहा हूँ और मैं इसे VB में अनुवाद करूँगा। धन्यवाद।
InteXX

मुझे पता है कि यह पुराना है लेकिन मैंने पाया कि यह सबसे कम हैक करने वाला समाधान था। चूँकि मैं अभी भी अपना इंटरफ़ेस UserControl से बाँधना चाहता था, इसलिए मैंने इंटरफ़ेस में एक UserControlगुण जोड़ा और कहा कि जब भी मुझे इसे सीधे एक्सेस करने की आवश्यकता हो। अपने इंटरफ़ेस कार्यान्वयन में, मैं UserControl का विस्तार करता हूं और UserControlसंपत्ति कोthis
Chanban

3

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

अद्यतन: मैंने उस दूसरे प्रश्न के उत्तर में एक दस्तावेज कोड नमूना शामिल किया । वहां कोड काम करता है, लेकिन कभी-कभी मुझे एक साफ / निर्माण चक्र से गुजरना पड़ता है, जैसा कि मेरे जवाब में यह काम करने के लिए मिलता है।


3

मुझे ऐसे लोगों के लिए कुछ सुझाव मिले हैं, जो कहते हैं कि TypeDescriptionProviderजुआन कार्लोस डियाज़ काम नहीं कर रहे हैं और न ही सशर्त संकलन पसंद करते हैं:

सबसे पहले, आपको फॉर्म कोड डिज़ाइनर में काम करने के लिए विज़ुअल स्टूडियो को फिर से शुरू करना पड़ सकता है (मुझे करना था, सरल पुनर्निर्माण काम नहीं किया - या हर बार नहीं)।

मैं सार आधार फॉर्म के मामले के लिए इस समस्या का समाधान प्रस्तुत करूंगा। मान लें कि आपके पास एक BaseFormवर्ग है और आप चाहते हैं कि इस पर आधारित कोई भी प्रपत्र डिजाइन योग्य हो (यह होगा Form1)। TypeDescriptionProviderके रूप में जुआन कार्लोस डियाज़ द्वारा प्रस्तुत भी मेरे लिए काम नहीं किया। यहां बताया गया है कि मैंने इसे कैसे काम किया, इसे मिडलक्लास समाधान (स्मेलच द्वारा) के साथ जोड़कर, लेकिन सशर्त संकलन के बिना#if DEBUG और कुछ सुधारों के साथ:

[TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider<BaseForm, BaseFormMiddle2>))]   // BaseFormMiddle2 explained below
public abstract class BaseForm : Form
{
    public BaseForm()
    {
        InitializeComponent();
    }

    public abstract void SomeAbstractMethod();
}


public class Form1 : BaseForm   // Form1 is the form to be designed. As you see it's clean and you do NOTHING special here (only the the normal abstract method(s) implementation!). The developer of such form(s) doesn't have to know anything about the abstract base form problem. He just writes his form as usual.
{
    public Form1()
    {
        InitializeComponent();
    }

    public override void SomeAbstractMethod()
    {
        // implementation of BaseForm's abstract method
    }
}

BaseForm वर्ग पर विशेषता को देखें। फिर आपको बस TypeDescriptionProviderऔर दो मध्यम वर्गों की घोषणा करनी है , लेकिन चिंता न करें, वे फॉर्म 1 के डेवलपर के लिए अदृश्य और अप्रासंगिक हैं । पहला एक अमूर्त सदस्यों को लागू करता है (और बेस क्लास को गैर सार बनाता है)। दूसरा एक खाली है - यह काम करने के लिए वीएस फॉर्म डिजाइनर के लिए आवश्यक है। तब आप दूसरी मध्यम वर्ग को असाइन करते TypeDescriptionProviderहैं BaseFormकोई सशर्त संकलन नहीं।

मुझे दो और समस्याएं हो रही थीं:

  • समस्या 1: डिजाइनर (या कुछ कोड) में फॉर्म 1 को बदलने के बाद यह फिर से त्रुटि दे रहा था (जब इसे फिर से डिजाइनर में खोलने की कोशिश कर रहा है)।
  • समस्या 2: बेसफ़ॉर्म के नियंत्रणों को गलत तरीके से रखा गया था जब फॉर्म 1 के आकार को डिजाइनर में बदल दिया गया था और फॉर्म को बंद कर दिया गया था और फॉर्म डिजाइनर में फिर से खोल दिया गया था।

पहली समस्या (आपके पास यह नहीं हो सकती है क्योंकि यह ऐसा कुछ है जो मुझे अपनी परियोजना में कुछ अन्य स्थानों पर परेशान करता है और आमतौर पर "एक्स टाइप करने के लिए एक्स टाइप नहीं कर सकता" अपवाद पैदा करता है)। मैं में इसे हल TypeDescriptionProviderद्वारा प्रकार के नाम की तुलना (FullName) के बजाय प्रकार की तुलना में (देखें नीचे)।

दूसरी समस्या। मुझे वास्तव में नहीं पता है कि फॉर्म 1 क्लास में बेस फॉर्म के नियंत्रण क्यों नहीं हैं और आकार बदलने के बाद उनकी स्थिति खो गई है, लेकिन मैंने इसे काम किया है (अच्छा समाधान नहीं - यदि आप कोई बेहतर जानते हैं, तो कृपया लिखें)। मैं बस बेसफार्म के बटन (जो कि नीचे-दाएं कोने में होना चाहिए) को बेसफोर्म के लोड इवेंट से असिंक्रोनसली तरीके से मंगवाए गए सही तरीके से ले जाता हूं: BeginInvoke(new Action(CorrectLayout));मेरे बेस क्लास में केवल "ओके" और "कैंसल" बटन होते हैं, इसलिए मामला सरल है।

class BaseFormMiddle1 : BaseForm
{
    protected BaseFormMiddle1()
    {
    }

    public override void SomeAbstractMethod()
    {
        throw new NotImplementedException();  // this method will never be called in design mode anyway
    }
}


class BaseFormMiddle2 : BaseFormMiddle1  // empty class, just to make the VS designer working
{
}

और यहाँ आपके पास थोड़ा संशोधित संस्करण है TypeDescriptionProvider:

public class AbstractControlDescriptionProvider<TAbstract, TBase> : TypeDescriptionProvider
{
    public AbstractControlDescriptionProvider()
        : base(TypeDescriptor.GetProvider(typeof(TAbstract)))
    {
    }

    public override Type GetReflectionType(Type objectType, object instance)
    {
        if (objectType.FullName == typeof(TAbstract).FullName)  // corrected condition here (original condition was incorrectly giving false in my case sometimes)
            return typeof(TBase);

        return base.GetReflectionType(objectType, instance);
    }

    public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
    {
        if (objectType.FullName == typeof(TAbstract).FullName)  // corrected condition here (original condition was incorrectly giving false in my case sometimes)
            objectType = typeof(TBase);

        return base.CreateInstance(provider, objectType, argTypes, args);
    }
}

और बस!

आपको अपने BaseForm के आधार पर रूपों के भविष्य के डेवलपर्स के लिए कुछ भी समझाने की ज़रूरत नहीं है और उन्हें अपने फ़ॉर्म को डिज़ाइन करने के लिए कोई चाल करने की ज़रूरत नहीं है! मुझे लगता है कि यह सबसे साफ समाधान हो सकता है (नियंत्रण को छोड़कर)।

एक और टिप:

यदि किसी कारण से डिज़ाइनर अभी भी आपके लिए काम करने से इनकार करता है, तो आप हमेशा कोड फ़ाइल में (या ) public class Form1 : BaseFormको बदलने , वीएस फॉर्म डिजाइनर में इसे संपादित करने और फिर इसे फिर से बदलने की सरल चाल कर सकते हैं । मैं सशर्त संकलन पर इस चाल को पसंद करता हूं क्योंकि यह गलत संस्करण को भूलने और जारी करने की संभावना कम हैpublic class Form1 : BaseFormMiddle1BaseFormMiddle2


1
इस समस्या को वीएस 2013 में जुआन के समाधान के साथ मैं हल कर रहा था; वी.एस. को पुनरारंभ करने पर नियंत्रण लगातार लोड होता है।
ल्यूक मेरेट

3

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

  <appSettings>
   <add key="EnableOptimizedDesignerReloading" value="false" />
  </appSettings>

2

चूंकि अमूर्त वर्ग public abstract class BaseForm: Formएक त्रुटि देता है और डिजाइनर के उपयोग से बचता है, मैं आभासी सदस्यों के उपयोग के साथ आया था। मूल रूप से, अमूर्त विधियों को घोषित करने के बजाय, मैंने यथासंभव न्यूनतम शरीर के साथ आभासी तरीकों की घोषणा की। यहाँ मैंने क्या किया है:

public class DataForm : Form {
    protected virtual void displayFields() {}
}

public partial class Form1 : DataForm {
    protected override void displayFields() { /* Do the stuff needed for Form1. */ }
    ...
}

public partial class Form2 : DataForm {
    protected override void displayFields() { /* Do the stuff needed for Form2. */ }
    ...
}

/* Do this for all classes that inherit from DataForm. */

चूंकि DataFormअमूर्त सदस्य के साथ एक अमूर्त वर्ग माना जाता था displayFields, इसलिए मैं अमूर्त से बचने के लिए आभासी सदस्यों के साथ इस व्यवहार को "नकली" करता हूं। डिजाइनर अब कोई शिकायत नहीं करता है और मेरे लिए सब कुछ ठीक है।

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


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

1

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

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


अफ़सोस, लेकिन यह अभी तक कैसे किया जाता है। ऐसा करने का एक सही तरीका है।
ओलिवर फ्रेडरिक

एक बेहतर तरीका है, स्मेलच का जवाब देखें
एलन चावल

-1

आप केवल abstractअलग वर्ग को इंटर किए बिना कीवर्ड में संकलित कर सकते हैं :

#if DEBUG
  // Visual Studio 2008 designer complains when a form inherits from an 
  // abstract base class
  public class BaseForm: Form {
#else
  // For production do it the *RIGHT* way.
  public abstract class BaseForm: Form {
#endif

    // Body of BaseForm goes here
  }

यह काम BaseFormकरता है, जिसमें कोई सार तरीके नहीं हैं ( abstractकीवर्ड इसलिए केवल क्लास के रनटाइम इंस्टेंटेशन को रोकता है)।

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