2008-08-10 16 views
5

मैं जो करना चाहता हूं वह निम्न जैसा है:कक्षा को विरासत के बिना एक गैर-गतिशील एक्शनस्क्रिप्ट 3 कक्षा में व्यवहार जोड़ना संभव है?

FooClass.prototype.method = function():String 
{ 
    return "Something"; 
} 

var foo:FooClass = new FooClass(); 
foo.method(); 

जो कहने के लिए है, मैं एक जेनरेट क्लास को एक ही विधि के साथ विस्तारित करना चाहता हूं, विरासत के माध्यम से नहीं बल्कि प्रोटोटाइप के माध्यम से।

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

लंबी कहानी छोटी, मैं एएस 3 के लिए सी # 3: एस एक्सटेंशन विधियों के नैतिक समकक्ष होना चाहता हूं।

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

+0

@ एआईबी सही है, मैंने इसे गलती की जब मैंने इसका परीक्षण किया। मैं भूल गया कि प्रोटोटाइप केवल कक्षा पर ही पहुंच योग्य है, न कि प्रत्येक ऑब्जेक्ट पर, इसलिए मेरे लिए मुझे रनटाइम त्रुटियां मिलीं। हालांकि, मेरा रैपर समाधान subclassing नहीं है, यह लपेट रहा है। रैपर वर्ग केवल मूल को बढ़ाता है ताकि यह वही प्रकार होगा। – Theo

उत्तर

3

हां, ऐसी चीज संभव है।

वास्तव में, आपका उदाहरण समाधान के बहुत करीब है।

foo["method"](); 

बजाय

foo.method(); 
1

@aib दुर्भाग्य से सही नहीं है की कोशिश करो। सख्त मोड (डिफ़ॉल्ट कंपाइलर मोड) मानना ​​एक्शनस्क्रिप्ट 3 में गैर-गतिशील वर्ग प्रकारों के प्रोटोटाइप को संशोधित करना संभव नहीं है। मुझे यह भी सुनिश्चित नहीं है कि यह गैर-सख्त मोड में संभव है।

एक विकल्प लपेट रहा है? मूल रूप से आप एक वर्ग है कि वस्तुओं आप वेब सेवा से मिलता है और सिर्फ आगे सब विधि है कि करने के लिए कॉल में से एक लेता है बनाने के लिए, लेकिन यह भी अपने स्वयं के तरीकों है:

public class FooWrapper extends Foo { 

    private var wrappedFoo : Foo; 

    public function FooWrapper(foo : Foo) { 
     wrappedFoo = foo; 
    } 

    override public function methodFromFoo() : void { 
     wrappedFoo.methodFromFoo(); 
    } 

    override public function anotherMethodFromFoo() : void { 
     wrappedFoo.anotherMethodFromFoo(); 
    } 

    public function newMethodNotOnFoo() : String { 
     return "Hello world!" 
    } 

} 

जब आप एक Foo के साथ काम करना चाहते हैं, लेकिन आपके पास Foo उदाहरण FooWrapper में आपको अतिरिक्त विधि की आवश्यकता है और इसके बजाय उस ऑब्जेक्ट के साथ काम करें।

यह सबसे सुविधाजनक समाधान नहीं है, बहुत सारे टाइपिंग हैं और यदि जेनरेट कोड बदलता है तो आपको FooWrapper कक्षा को हाथ से बदलना होगा, लेकिन जब तक आप जेनरेट कोड को संशोधित नहीं कर सकते हैं या तो आप जिस विधि को चाहते हैं या बनाना चाहते हैं कक्षा गतिशील मैं नहीं देखता कि यह कैसे किया जा सकता है।

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

4

@Theo: आप डिफ़ॉल्ट फ्लेक्स-config.xml (< सख्त > सच </सख्त >) और यहां तक ​​कि एक -compiler.strict पैरामीटर mxmlc के लिए पारित साथ 3.0.0.477 में अगले कार्य कैसे समझाएंगे?

Foo.as:

package 
{ 
    public class Foo 
    { 
     public var foo:String; 

     public function Foo() 
     { 
      foo = "foo!"; 
     } 
    } 
} 

footest।के रूप में:

package 
{ 
    import flash.display.Sprite; 

    public class footest extends Sprite 
    { 
     public function footest() 
     { 
      Foo.prototype.method = function():String 
      { 
       return "Something"; 
      } 

      var foo:Foo = new Foo(); 
      trace(foo["method"]()); 
     } 
    } 
} 

ध्यान दें कि ओपी ने कहा कि विरासत अस्वीकार्य था, जैसा कि जेनरेट कोड को संशोधित कर रहा था। (। अगर ऐसी बात, वर्ग परिभाषा में "गतिशील" जोड़कर नहीं थे शायद सबसे आसान समाधान हो जाएगा)

2

कितने तरीकों अपने वर्ग है के आधार पर यह काम कर सकते हैं:

वास्तविक कक्षा:

public class SampleClass 
{ 
    public function SampleClass() 
    { 
    } 

    public function method1():void { 
     Alert.show("Hi"); 
    } 

त्वरित आवरण:

var actualClass:SampleClass = new SampleClass(); 

var QuickWrapper:Object = { 
    ref: actualClass, 
    method1: function():void { 
     this.ref.method1(); 
    }, 
    method2: function():void { 
     Alert.show("Hello!"); 
    } 
}; 

QuickWrapper.method1(); 
QuickWrapper.method2(); 
1

बंदर पैचिंग एक (असजीला) विकल्प है।

उदाहरण के लिए, मान लीजिए कि आपको यह तथ्य पसंद नहीं है कि फ्लेक्स 3 स्प्राइटएस्सेट.एएस [7,7,7,7] (फ्लेक्स 2 के विपरीत) की डिफ़ॉल्ट सीमा मीट्रिक देता है। इसे ठीक करने के लिए, आप:

  1. SpriteAsset.as की एक प्रति बनाएं और /mx/core/SpriteAsset.as में अपनी परियोजना के लिए इसे जोड़ने
  2. संपादित करें आपकी स्थानीय प्रतिलिपि किसी भी समस्याओं को ठीक करने के लिए आप
  3. लगता है
  4. अपने एपी

Google और अधिक उदाहरणों और निर्देशों के लिए Google "flex monkey patch" चलाएं।