extjs4 - ExtJS में कक्षाओं / गुणों को ओवरराइड करने के लिए सबसे अच्छा अभ्यास?




override extjs4.1 (3)

मेरे पास Ext.form.field.Text और मैं setValue फ़ंक्शन को ओवरराइड करना चाहता हूं।

ExtJS में इस वर्ग कार्यक्षमता को ओवरराइड करने का अनुशंसित तरीका क्या है? Ext.override ?


Answers

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

Ext.define('my.application.form.field.Text' {
    override: 'Ext.form.field.Text'
    getValue: function () {
        // your custom functionality here
        arguments[1] = false;

        // callParent can be used if desired, or the method can be 
        // re-written without reference to the original
        this.callParent(arguments)
    }
});

मैं अभी भी Ext 5 का उपयोग कर रहा हूं, इसलिए मैं इस फ़ाइल को अपने application.js में लोड कर दूंगा और इसे आवश्यक सरणी में जोड़ दूंगा जो वैश्विक स्तर पर ऐप पर ओवरराइड लागू करता है। मुझे लगता है कि एक्स्ट्रा 6 परियोजनाओं में एक ओवरराइड फ़ोल्डर शामिल है और बस उस फ़ाइल को उस फ़ोल्डर में जोड़ना सुनिश्चित करता है कि ओवरराइड लागू होता है।


स्पष्टीकरण के लिए: वास्तविक वर्ग संशोधन से मेरा मतलब है कि एक वर्ग का एक स्थायी स्थायी संशोधन / विस्तार , जिसे कक्षा को विस्तारित करके हमेशा किया जाना चाहिए। लेकिन यह केवल एक विशिष्ट समस्या (बग-फिक्स, इत्यादि) के लिए एक अस्थायी समाधान नहीं है

आपके पास कम से कम चार विकल्प हैं (कैसे) कक्षाओं के सदस्यों को ओवरराइड करना है

  • प्रोटोटाइप मुझे लगता है कि यह अच्छी तरह से जाना जाता है और आपको कक्षा के सभी उदाहरणों के लिए एक सदस्य को ओवरराइड करने की अनुमति देता है। आप इसका इस्तेमाल कर सकते हैं

    Ext.view.View.prototype.emptyText = "";
    

    जबकि आप इसका उपयोग नहीं कर सकते हैं

    // callParent is NOT allowed for prototype
    Ext.form.field.Text.prototype.setValue = function(val) {
        var me = this,
            inputEl = me.inputEl;
    
        if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
            inputEl.removeCls(me.emptyCls);
            me.valueContainsPlaceholder = false;
        }
    
        me.callParent(arguments);
    
        me.applyEmptyText();
        return me;
    };
    

    यहां एक JSFiddle

    इस संस्करण का उपयोग वास्तविक वर्ग संशोधन के लिए नहीं किया जाना चाहिए।

  • Ext.override प्रोटोटाइप के लगभग समान होता है लेकिन यह Ext.override क्लास-सिस्टम पर पूरी तरह से लागू होता है जो आपको callParent() का उपयोग करने की अनुमति देता है

    आप इसका इस्तेमाल कर सकते हैं

    // callParent is allowed for override
    Ext.override('Ext.form.field.Text', {
        setValue: function(val) {
            this.callParent(['In override']);
            return this;
        }
    });
    

    यहां एक JSFiddle (सीपी त्रुटि तय! @nogridbag के लिए धन्यवाद)

    केस का प्रयोग करें: मुझे एक रेडियोग्रुप का एक बुरा व्यवहार (मुझे लगता है कि अभी भी मौजूद है) का सामना करना पड़ा जहां ExtJS मूल्य की सही सेटिंग के लिए ऑब्जेक्ट (कुंजी-मूल्य-जोड़ी) की अपेक्षा करता है। लेकिन मेरे पास बैकएंड पर सिर्फ एक पूर्णांक है। मैंने पहले setValue() विधि के लिए Ext.override का उपयोग करके एक फिक्स लगाया और बाद में रेडियोग्रुप से विस्तार किया। वहां मैं दिए गए मान से केवल एक कुंजी-मूल्य-जोड़ बना देता हूं और उसके साथ मूल विधि को कॉल करता हूं।

    जैसा कि @rixo उल्लेख है, इसका उपयोग आवृत्ति सदस्य को ओवरराइड करने के लिए किया जा सकता है। और इसलिए मिश्रणों को ओवरराइड करने के लिए भी योग्यता प्राप्त की जा सकती है (मैंने इसे कभी परीक्षण नहीं किया)

    var panel = new Ext.Panel({ ... });
    Ext.override(panel, {
        initComponent: function () {
            // extra processing...
    
            this.callParent();
        }
    });
    

    इस संस्करण का उपयोग वास्तविक वर्ग संशोधन के लिए नहीं किया जाना चाहिए।

  • अतिरिक्त व्यवहार और प्रतिपादन लागू करने के लिए एक मौजूदा वर्ग का विस्तार करना । इस प्रकार का उपयोग एक उप प्रकार का निर्माण करने के लिए करें जो मूल प्रकार को खोए बिना अलग व्यवहार करता है।

    निम्नलिखित उदाहरण में हम लेबलकोल्ड को बदलने के लिए एक विधि के साथ टेक्स्टफील्ड का विस्तार करते हैं, जिसे setColored नामक एक नया मान सेट करते समय सेट लेबल पर निकालने के लिए setValue विधि को ओवरराइड करते हैं, जब setValue को सीधे कॉल किया जाता है

    Ext.define('Ext.ux.field.Text',{
        extend: 'Ext.form.field.Text',
        widget: 'uxtextfield',
        setColored: function(val,color) {
            var me = this;
            if (me.settedCls) {
                me.removeCls(me.settedCls);
            }
            me.addCls(color);
            me.settedCls = color;
            me.setValue(val,true);
        },
        setValue: function(val,take) {
            var me = this;
            if (!take && me.settedCls) {
                me.removeCls(me.settedCls);
            }
            me.callParent(arguments);
            return me;
        }
    });
    

    यहां एक JSFiddle

  • प्रति उदाहरण ओवरराइडिंग वास्तव में दुर्लभ मामलों में होगी और हो सकता है कि सभी गुणों पर लागू न हो। ऐसे मामले में (जहां मेरे पास एक उदाहरण नहीं है) आपके पास एक अलग व्यवहार की आवश्यकता है और आप केवल प्रति उदाहरण एक सेटिंग ओवरराइड करने पर विचार कर सकते हैं। मूल रूप से आप इस तरह की चीजें करते हैं जब आप वर्ग निर्माण पर कॉन्फ़िगरेशन लागू करते हैं लेकिन अधिकांश समय आप कॉन्फ़िगरेशन गुणों के डिफ़ॉल्ट मानों को ओवरराइड करते हैं लेकिन आप उन संदर्भों को ओवरराइड करने में भी सक्षम होते हैं जो संदर्भ कार्यों को ओवरराइड करते हैं। यह पूरी तरह से कार्यान्वयन को ओवरराइड करता है और आप बेसटाइप (यदि कोई मौजूद है) तक पहुंच नहीं कर सकते हैं जिसका अर्थ है कि आप callParent उपयोग नहीं कर सकते हैं। आप इसे setValue साथ setValue सकते हैं यह देखने के लिए कि इसे मौजूदा श्रृंखला पर लागू नहीं किया जा सकता है। लेकिन फिर, आपको कुछ दुर्लभ मामलों का सामना करना पड़ सकता है जहां यह उपयोगी है, भले ही यह विकास के दौरान हो और उत्पादक के लिए पुन: कार्यान्वित हो। इस तरह के मामले के लिए आपको उपरोक्त वर्णित Ext.override का उपयोग करके विशिष्ट बनाया गया है के बाद ओवरराइड लागू करना चाहिए।

    महत्वपूर्ण: यदि आप Ext.override उपयोग नहीं करते हैं तो आपको इसे कॉल करके क्लास-इंस्टेंस तक पहुंच नहीं है!

अगर मुझे कुछ याद आया या कुछ (सही नहीं) सही है, तो कृपया टिप्पणी करें या संपादित करने के लिए स्वतंत्र महसूस करें।

जैसा कि @Eric द्वारा टिप्पणी की गई है

इनमें से कोई भी तरीका आपको मिश्रित ओवरराइड (जैसे Ext.form.field.Field) को ओवरराइड करने की अनुमति देता है। चूंकि कक्षा को परिभाषित करते समय मिश्रित कार्यों को कक्षाओं में कॉपी किया जाता है, इसलिए आपको अपने ओवरराइड को लक्षित कक्षाओं में सीधे लागू करना होगा


यहां एक उदाहरण दिया गया है जो सुपर कन्स्ट्रक्टर में ओवरराइड करने योग्य विधि को कॉल करते समय होने वाली तार्किक समस्याओं का खुलासा करता है।

class A {

    protected int minWeeklySalary;
    protected int maxWeeklySalary;

    protected static final int MIN = 1000;
    protected static final int MAX = 2000;

    public A() {
        setSalaryRange();
    }

    protected void setSalaryRange() {
        throw new RuntimeException("not implemented");
    }

    public void pr() {
        System.out.println("minWeeklySalary: " + minWeeklySalary);
        System.out.println("maxWeeklySalary: " + maxWeeklySalary);
    }
}

class B extends A {

    private int factor = 1;

    public B(int _factor) {
        this.factor = _factor;
    }

    @Override
    protected void setSalaryRange() {
        this.minWeeklySalary = MIN * this.factor;
        this.maxWeeklySalary = MAX * this.factor;
    }
}

public static void main(String[] args) {
    B b = new B(2);
    b.pr();
}

परिणाम वास्तव में होगा:

minWeeklySalary: 0

maxWeeklySalary: 0

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

मुझे उम्मीद है कि किसी की मदद करेगा।