2012-01-06 22 views
11

मैं जावा 6 का उपयोग कर रहा हूं।मैं कक्षा के सामान्य प्रकार को प्राप्त करने के लिए एक आंतरिक वर्ग कैसे प्राप्त करूं?

मुझे अपनी आंतरिक कक्षा को उसी सामान्य वर्ग का उपयोग करने के लिए अपनी संलग्न कक्षा के रूप में उपयोग करने में परेशानी हो रही है। वर्तमान में मैं

public class TernarySearchTree <T> { 
    ... 
    protected class TSTNode <T> { 
     // index values for accessing relatives array 
     protected static final int PARENT = 0, LOKID = 1, EQKID = 2, HIKID = 3; 
     protected char splitchar; 
     protected TSTNode <T> [] relatives; 
     private T data; 

     protected TSTNode(char splitchar, TSTNode <T> parent) { 
      this.splitchar = splitchar; 
      relatives = new TSTNode[4]; 
      relatives[PARENT] = parent; 
     } 
    } 
} 

है अभी मैं चेतावनी

प्रकार पैरामीटर टी प्रकार टी

छिपा है अगर मैं भीतरी वर्ग से प्रकार पैरामीटर को दूर पाने यानी हटाने (<T> teh protected class TSTNode<T> लाइन से), तो मुझे लाइन relatives = new TSTNode[4] पर एक संकलन त्रुटि मिलती है।

मैं सबकुछ सही कैसे कर सकता हूं?

+4

आप एक संकलन त्रुटि मिलती है, तो आप ** को शामिल करना चाहिए ** संकलन त्रुटि आपके प्रश्न में संदेश! लेकिन यह मेरे लिए ठीक काम करता है। बस सुनिश्चित करें कि आप 'रिश्तेदारों' के * घोषणा * पर '' से छुटकारा पाएं। उस ने कहा, आप हमेशा 'टीएसटीएनओडी' स्थिर बना सकते हैं और 'ई' जैसे एक अलग पैरामीटर का उपयोग कर सकते हैं। –

+0

जेनेरिक सरणी बनाने के लिए क्यों संभव नहीं है: http://stackoverflow.com/questions/2927391/whats-the-reason-i-cant-create-generic-array-types-in-java –

+0

क्या TSTNode को एक्सेस करने की आवश्यकता है उदाहरण फ़ील्ड या TernarySearchTree से तरीकों? –

उत्तर

8

आप या तो कर सकते हैं:

  • TSTNode (यानी, यह कर से <T> प्रकार पैरामीटर को दूर गैर-जेनेरिक) - इसके पास अभी भी बाहरी <T> तक पहुंच होगी।

  • <T>TSTNode में U में टाइप पैरामीटर का नाम बदलें।

[अद्यतन]

नीचे अपने कोड के पुनर्लेखन के लिए चार अलग-अलग तरीके हैं। वे सभी संकलित करते हैं। मुझे लगता है कि आपको EnumMap के उपयोग पर विचार करना चाहिए (नीचे संस्करण 4 देखें)।

संस्करण 1: आंतरिक वर्ग में एक अलग नामित प्रकार पैरामीटर का उपयोग करें। आपको सरणी के बजाय सूची का उपयोग करने की आवश्यकता है।

public class TernarySearchTree<T> { 

    protected class TSTNode<U> { 
     // index values for accessing relatives array: 
     protected static final int PARENT = 0, LOKID = 1, EQKID = 2, HIKID = 3; 

     protected char splitchar; 
     protected List<TSTNode<U>> relatives; 
     private U data; 

     protected TSTNode(char splitchar, TSTNode<U> parent) { 
     this.splitchar = splitchar; 
     relatives = new ArrayList<TSTNode<U>>(); 
     for (int i = 0; i < HIKID; ++i) { // Allocate 4 slots in relatives 
      relatives.add(null); 
     } 
     relatives.set(PARENT, parent); 
     }   
    } 

    private TSTNode<T> node; // When you use it, pass T as U 

    public TernarySearchTree() { 
     node = new TSTNode<T>(',', null); // When you use it, pass T as U 
    } 
    } 

संस्करण 2: वर्ग enclosing से विरासत टी

public class TernarySearchTree<T> { 

    protected class TSTNode { 
     // index values for accessing relatives array: 
     protected static final int PARENT = 0, LOKID = 1, EQKID = 2, HIKID = 3; 

     protected char splitchar; 
     protected List<TSTNode> relatives; 
     private T data; 

     protected TSTNode(char splitchar, TSTNode parent) { 
     this.splitchar = splitchar; 
     relatives = new ArrayList<TSTNode>(); 
     for (int i = 0; i < HIKID; ++i) { // Allocate 4 slots in relatives 
      relatives.add(null); 
     } 
     relatives.set(PARENT, parent); 
     } 
    } 

    private TSTNode node; 

    public TernarySearchTree() { 
     node = new TSTNode(',', null); 
    } 
    } 

संस्करण 3: (क सूची के बजाय) एक मानचित्र का उपयोग

public class TernarySearchTree<T> { 

    protected class TSTNode { 
     // index values for accessing relatives array: 
     protected static final int PARENT = 0, LOKID = 1, EQKID = 2, HIKID = 3; 

     protected char splitchar; 
     protected Map<Integer, TSTNode> relatives; 
     private T data; 

     protected TSTNode(char splitchar, TSTNode parent) { 
     this.splitchar = splitchar; 
     // Create a hash map. No need to pre-allocate! 
     relatives = new HashMap<Integer, TSTNode>(); 
     relatives.put(PARENT, parent); // set -> put 
     } 
    } 

    private TSTNode node; 

    public TernarySearchTree() { 
     node = new TSTNode(',', null); 
    } 
    } 
} 

संस्करण 4: सूचकांक को एक enum के रूप में परिभाषित करें + एक EnunMap का उपयोग करें (एक हैश एम के बजाय पी)

public class TernarySearchTree<T> { 

    protected static enum Index { 
     PARENT, LOKID, EQKID, HIKID; 
    } 

    protected class TSTNode {  
     protected char splitchar; 
     protected EnumMap<Index, TSTNode> relatives; 
     private T data; 

     protected TSTNode(char splitchar, TSTNode parent) { 
     this.splitchar = splitchar; 
     // Create an EnumMap. 
     relatives = new EnumMap<Index, TSTNode>(Index.class); 
     relatives.put(Index.PARENT, parent); 
     } 
    } 

    private TSTNode node; 

    public TernarySearchTree() { 
     node = new TSTNode(',', null); 
    } 
    } 

[अपडेट 2] को ध्यान में रखना एक बात: Use EnumMap instead of ordinal indexing

+0

समाधान 1: संकलित नहीं करता है। –

+0

समाधान 2: टी और यू अलग होंगे, और शायद वह सामान्य प्रकारों को समान बनाना चाहते हैं। –

+0

मैंने समाधान 4 का उपयोग किया। धन्यवाद, - – Dave

2

मैं नहीं जानता कि आप क्या करने की कोशिश कर रहे हैं लेकिन, इस sollution है:

public class TernarySearchTree<T> { 

protected class TSTNode<E extends T> { 
    protected static final int PARENT = 0, LOKID = 1, EQKID = 2, HIKID = 3; 
    protected char splitchar; 
    protected TSTNode<E>[] relatives; 
    private E data; 

    protected TSTNode(char splitchar, TSTNode<E> parent) { 
     this.splitchar = splitchar; 
     relatives = new TSTNode[4]; 
     relatives[PARENT] = parent; 
    } 
} 
} 
इस के साथ

आप एक ही पंक्ति में एक त्रुटि के बजाय चेतावनी दी मिलता है।

एक सूची का उपयोग करना संभव है एक बेहतर समाधान (कोई चेतावनी)

public class TernarySearchTree<T> { 

    protected class TSTNode<E extends T> { 
     protected static final int PARENT = 0, LOKID = 1, EQKID = 2, HIKID = 3; 
     protected char splitchar; 
     protected List<TSTNode<E>> relatives; 
     private E data; 

     protected TSTNode(char splitchar, TSTNode<E> parent) { 
      this.splitchar = splitchar; 
      relatives = new ArrayList<TSTNode<E>>(); 
      relatives.set(PARENT, parent); 
     } 
    } 
} 
0

मुझे लगता है कि तुम क्या चाहते है कुछ की तरह:

class Tree<T> { 
    Node<T> head; 

    static class Node<T> { 
     List<Node<T>> relatives = new ArrayList<Node<T>>(); 
     T value; 
    } 
} 

यहाँ, एक पेड़ के सिर नोड पेड़ के समान ही T है, और प्रत्येक सापेक्ष नोड में T पैरेंट नोड के समान होता है, इसलिए पेड़ के सभी नोड्स के समान पेड़ के रूप में समान मूल्य प्रकार होगा च।

मैंने ArrayList का उपयोग किया क्योंकि सरणी में सामान्य प्रकार नहीं हो सकते हैं।

+0

यह प्रोग्राम सेमेन्टिक्स को बदलता है क्योंकि नोड अब ट्री सदस्यों तक नहीं पहुंच सकता है (मूल समस्या में यह कर सकता है)। लेकिन यह एक वैध विकल्प है। –

+0

नोड में हमेशा एक स्पष्ट वृक्ष फ़ील्ड हो सकता है यदि इसे वास्तव में अपने मालिक को वापस संदर्भित करने की आवश्यकता हो, लेकिन मेरा अनुमान था कि डेव वास्तव में इसे आंतरिक कक्षा के रूप में उपयोग नहीं कर रहा था। –

+0

मैं आपसे सहमत हूं, आंतरिक कक्षा शायद आवश्यक नहीं है। –

3

सामान्य सरणी निर्माण जब आप भीतरी वर्ग से टी हटाने के लिए संकलन त्रुटि के रूप में:

क्योंकि यह एक गैर स्थिर भीतरी वर्ग है, यह बाहरी वर्ग के प्रकार पैरामीटर के दायरे के भीतर है। जिसका अर्थ है कि यह इसके बाहरी वर्ग के प्रकार पैरामीटर

द्वारा पैरामीटर द्वारा भी पैरामीटर किया गया है, इसलिए जब आप TSTNode लिखते हैं तो इसका मूल रूप से TernarySearchTree<T>.TSTNode (टी यहां बाहरी टी है)। तो TSTNode अभी भी एक सामान्य प्रकार है (भले ही आप स्पष्ट रूप से किसी भी ब्रैकेट को नहीं देखते हैं), और सामान्य प्रकार की सरणी बनाना विफल हो जाता है।

आप नाम को मैन्युअल रूप से अर्हता प्राप्त करके TSTNode के कच्चे प्रकार का संदर्भ ले सकते हैं: TernarySearchTree.TSTNode

तो new TernarySearchTree.TSTNode[4] उत्तर है।

पी.एस. (क्या वह आप सामान्य प्रकार के सरणियों के साथ साथ जीना है) आप एक अनियंत्रित चेतावनी है, जो आप उपेक्षा कर सकते हैं मिल जाएगा आंतरिक वर्ग से प्रकार पैरामीटर को हटाने का लगभग निश्चित रूप से सही विकल्प है, क्योंकि जावा में गैर स्थैतिक आंतरिक कक्षाएं बाहरी वर्ग के उदाहरण के संदर्भ में अंतर्निहित रूप से संदर्भित होती हैं। तो यह पहले से ही बाहरी टी के साथ पैरामीटरकृत है। यदि आप बस एक ही टी का उपयोग करना चाहते हैं, तो एक और घोषित न करें।

0

Itay Maman's solution पर एक भिन्नता।

इस ओपी की तुलना में एक व्यापक प्रश्न का उत्तर है पूछ रहा है: मैं कैसे केवल आंतरिक रूप जावा में प्रयोग की जाने वाली जेनरिक की एक सरणी बना सकता हूँ? (यह समाधान उपयोगकर्ता को वापस आने के लिए जेनेरिक सरणी बनाने के लिए उपयोग नहीं करना है - यह unsafe as is well recognized होगा।)

संपादित करें: संस्करण 5: एक सरणी के साथ enums का उपयोग करें। (मुझे लगता है कि V4 ओपी के लिए बेहतर है, लेकिन आप जेनरिक के साथ एक सरणी की आवश्यकता है, यहाँ है कैसे - योशिय्याह योडर)

public class TernarySearchTreeWithArray<T> { 

    protected static enum Index { 
     PARENT, LOKID, EQKID, HIKID, ARRAY_SIZE; 
    } 

    protected class TSTNode<U> { 
     protected char splitchar; 

     @SuppressWarnings("unchecked") 
     protected TSTNode<U>[] relatives = (TSTNode<U>[]) new TSTNode[Index.ARRAY_SIZE.ordinal()]; 

     private U data; 

     protected TSTNode(char splitchar, TSTNode<U> parent) { 
      this.splitchar = splitchar; 
      relatives[Index.PARENT.ordinal()] = parent; 
     } 
    } 

    private TSTNode<T> root; // When you use it, pass T as U 

    public TernarySearchTreeWithArray() { 
     root = new TSTNode<>(',', null); // When you use it, pass T as U 
    } 
} 
संबंधित मुद्दे

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