2012-12-19 21 views
5

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

कोड का एक संक्षिप्त संस्करण इस प्रकार दिखाई देंगे:

import java.util.ArrayList; 
import java.util.List; 

public class NcgNode { 
    private List<NcgNode> nodeList_ = null; 
    private List<? extends NcgNode> nodeListSrc_ = null; 
    private List<? super NcgNode> nodeListSink_ = null; 

    public <N extends NcgNode> void addNode(N node) { 
     if (nodeList_ == null) { 
      nodeList_ = new ArrayList<NcgNode>(); 
      nodeListSrc_ = nodeList_; 
      nodeListSink_ = nodeList_; 
     } 
     nodeListSink_.add(node); 
    } 

    @SuppressWarnings("unchecked") 
    // Any way to avoid this? 
    public <N extends NcgNode> N getNode(int n) { 
     if ((nodeList_ == null) || (n >= nodeList_.size())) 
      return null; 
     // causes unchecked warning: 
     return (N) nodeListSrc_.get(n); 
    } 
} 

class DcgNode extends NcgNode { 
    // enables DCG algorithms, etc 
} 

class DagNode extends DcgNode { 
    // enables DAG algorithms, etc. 
} 

इस डिजाइन करने के लिए एक बेहतर तरीका है? "आत्म घिरा प्रकार" बाहर

public NcgNode getNode(int n) { 
    if ((nodeList_ == null) || (n >= nodeList_.size())) { 
    return null; 
} 

return (NcgNode) nodeListSrc_.get(n); 
} 

उत्तर

0

इस तरह के नीचे के रूप में अपने विधि को संशोधित। (संपादित करें: यकीन नहीं मैं नीचे वोट यहाँ समझते हैं),

आपका जड़ वर्ग सार होना चाहिए और वास्तविक नोड प्रकार N वर्ग के लिए एक प्रकार पैरामीटर होना चाहिए

public abstract class AbstractNode< N extends AbstractNode<N> > { 
    private List<N> nodeList_ = null; 

    public synchronized void addNode(N node) { 
     if (nodeList_ == null) 
      nodeList_ = new ArrayList<N>(); 
     nodeList_.add(node); 
    } 

    public N getNode(int n) { 
     if (nodeList_ == null || n >= nodeList_.size()) 
      throw new NoSuchElementException(); 
     return nodeList_.get(n); 
    } 
} 

कंक्रीट उपवर्गों में के रूप में कर सकते हैं फिर अपने स्वयं के प्रकार एन के रूप में आपूर्ति करें। गहरी विरासत पदानुक्रमों के लिए, "माई टाइप" को एक और अमूर्त वर्ग के साथ जीवित रखें।

class NcgNode extends AbstractNode<NcgNode> { 
} 

abstract class AbstractDcgNode< N extends AbstractDcgNode<N> > extends AbstractNode<N> { 
    // enables DCG algorithms, etc 
} 

class DcgNode extends AbstractDcgNode<DcgNode> { 
} 

class DagNode extends AbstractDcgNode<DagNode> { 
    // enables DAG algorithms, etc 
} 
+3

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

0

की जांच:

+0

1) "स्वयं-बाध्य प्रकार" जावा में काम नहीं करते हैं। 2) यदि आप प्रतिस्थापित '' AbstractNode साथ 'AbstractNode ' और 'AbstractDcgNode <एन फैली AbstractDcgNode >' 'साथ AbstractDcgNode ' यह उसी तरह – newacct

+0

आप टिप्पणी 1 के बारे में अधिक विशिष्ट हो सकता है काम करेगा <एन AbstractNode फैली>) ?कोई भी इस बात को लागू नहीं कर सकता कि एक प्रकार पैरामीटर इसे घोषित करने वाले वर्ग को बाध्य करता है, लेकिन यह टिप्पणी 2 के करीब है) सुझाव जो सख्ती से अधिक कार्यक्रमों को संकलित करने की अनुमति देता है - और ओपी से अधिक की तलाश में था। –

1

बस अपनी सूची प्रकार NcgNode है, आप अभी भी इन सूचियों में NcgNode की उपवर्गों रख सकते हैं बनाने जैसे

private List<NcgNode> nodeListSrc_ = null; 

1

आपको इसे निम्न की तरह कुछ करना चाहिए। बच्चों के प्रकार पर पैरामीटरकृत एक अमूर्त वर्ग (NcgNode) में परिभाषित विधियां हैं। इस प्रकार, addNode और getNode आसानी से लिखा जा सकता है। फिर आपके पास विशिष्ट कार्यान्वयन होंगे (मैंने DcgNode और DagNode का उपयोग किया था; सुनिश्चित नहीं है कि यह वही है जो आप चाहते हैं) इसके उप-वर्ग बनें, स्वयं पर पैरामीटरकृत करें। यह आपको बाद में (नीचे देखें) एल्गोरिदम की अनुमति देता है जिसके लिए एक नोड के बच्चे नोड के समान प्रकार के होते हैं।

public abstract class NcgNode<N> { 
    private List<N> nodeList_ = null; 

    public void addNode(N node) { 
     if (nodeList_ == null) { 
      nodeList_ = new ArrayList<N>(); 
     } 
     nodeList_.add(node); 
    } 

    // Any way to avoid this? 
    public N getNode(int n) { 
     if ((nodeList_ == null) || (n >= nodeList_.size())) 
      return null; 
     return nodeList_.get(n); 
    } 
} 

class DcgNode extends NcgNode<DcgNode> { 
    // enables DCG algorithms, etc 
} 

class DagNode extends NcgNode<DagNode> { 
    // enables DAG algorithms, etc. 
} 

//... 
static <N extends NcgNode<N>> void someAlgorithm(N node) { } 

DagNode का आपका विचार किया जा रहा DcgNode का एक उपवर्ग, सुरक्षित नहीं किया जा सकता है क्योंकि अगर एक DagNode "है-एक" DcgNode, तो मतलब है कि आप अपने बच्चे को, जो आप क्या नहीं है के रूप में यह किसी भी DcgNode डाल सकते हैं चाहते हैं।

+0

क्या होगा यदि आप डीसीएनएनओडी या डैग्नोड को भी विस्तारित करना चाहते हैं? – Sarevok

+0

यदि मैं एक सूची स्टोर करना चाहता हूं जो डीसीजीएनओडी और डैग्नोड दोनों को स्टोर कर सकता है, तो क्या मुझे इसे घोषित करना चाहिए? संकलक एक चेतावनी दिखाता है अगर मैं इसे इस तरह घोषित करता हूं क्योंकि मैं कच्चे प्रकार का उपयोग कर रहा हूं। – Sarevok

संबंधित मुद्दे