जावा में ऑब्जेक्ट जैसी संरचना


195

क्या यह जावा की तरह पूरी तरह से वस्तुओं जैसी संरचना बनाने के खिलाफ है?

class SomeData1 {
    public int x;
    public int y;
}

मैं एक्सेसर्स और म्यूटेटर्स के साथ एक क्लास देख सकता हूं जैसे कि जावा अधिक।

class SomeData2 {
    int getX();
    void setX(int x);

    int getY();
    void setY(int y);

    private int x;
    private int y;
}

पहले उदाहरण से वर्ग तर्कसंगत रूप से सुविधाजनक है।

// a function in a class
public int f(SomeData1 d) {
    return (3 * d.x) / d.y;
}

यह उतना सुविधाजनक नहीं है।

// a function in a class
public int f(SomeData2 d) {
    return (3 * d.getX()) / d.getY();
}

9
सार्वजनिक परिवर्तनशील फ़ील्ड के बजाय, सार्वजनिक अपरिवर्तनीय फ़ील्ड या पैकेज-स्थानीय परिवर्तनशील फ़ील्ड पर विचार करें। या तो बेहतर होगा IMHO।
बजे पीटर लॉरी

याद रखें कि, जबकि गेटर्स और सेटर्स बदसूरत / क्रिया हैं, यह जावा के दिल की तरह है। यह एक गैर-संक्षिप्त भाषा है। दूसरी तरफ, हालाँकि, आपको कभी भी ऐसा नहीं करना चाहिए, क्योंकि आपका आईडीई आपके लिए यही करता है। एक गतिशील भाषा में आपको कम टाइप करना पड़ता है, लेकिन आपको टाइप करना होता है (आम तौर पर, हालांकि आईडीई मदद कर सकता है)।
दान रोसेनस्टार्क

विडंबना यह है कि, जबकि OO के पास एनकैप्सुलेशन के संदर्भ में ताकत है, यह सीपीयू और स्टोरेज-वार भुगतान किया जाना है। कचरा संग्रहकर्ता (लगभग पूरी तरह से) इस बात की चिंता को दूर करता है कि कब वस्तु संदर्भों को साफ किया जाना चाहिए। वर्तमान प्रवृत्ति सी-जैसे स्ट्रक्चर्स ऑफ-हीप को नियोजित करके पूर्ण-चक्र जा रही है। यह कैशिंग-प्रकार के समाधान, अंतर प्रक्रिया संचार, तेजी से मेमोरी-सघन संचालन, जीसी ओ / एच के लिए एकदम सही है और यहां तक ​​कि आपके डेटा-सेट के लिए कम भंडारण ओ / एच से भी लाभ उठा सकता है। यदि आप जानते हैं कि आप क्या कर रहे हैं, तो आप यह सवाल नहीं पूछेंगे ... तो फिर से सोचें!
user924272

@ user924272: Re "C- जैसे स्ट्रक्चर्स ऑफ-हीप को नियोजित करके वर्तमान प्रवृत्ति पूर्ण-चक्र जा रही है"। जो आप जावा में करेंगे कैसे ??? IMHO, यह एक ऐसा क्षेत्र है जहाँ जावा अपनी आयु दिखा रहा है ...
टूलमेकरसैट

@ToolmakerSteve -मैं एक सर्कल देख रहा हूँ। में ही अकेला नहीं हूँ। अज़ुल जैसी कंपनियां पॉज़-कम कचरा संग्रह पर गर्म हैं। जावा पुराना है। सच। इंजीनियर जो एक कमजोरी को हाजिर करते हैं और इसके बारे में कुछ करते हैं, बजाय विलाप के? वे सम्मान के पात्र हैं! +10 से अज़ुल मेरे लिए :-)
user924272

जवाबों:


62

यह आमतौर पर चर्चा का विषय है। ऑब्जेक्ट में सार्वजनिक फ़ील्ड बनाने का दोष यह है कि आपके पास इसके लिए निर्धारित मानों पर कोई नियंत्रण नहीं है। समूह परियोजनाओं में जहां एक ही कोड का उपयोग करने वाले कई प्रोग्रामर हैं, दुष्प्रभावों से बचने के लिए यह महत्वपूर्ण है। इसके अलावा, कभी-कभी क्षेत्र की वस्तु की एक प्रति लौटाना या इसे किसी तरह बदलना आदि बेहतर होता है। आप अपने परीक्षणों में ऐसे तरीकों का मज़ाक उड़ा सकते हैं। यदि आप एक नया वर्ग बनाते हैं तो आप सभी संभावित कार्यों को नहीं देख सकते हैं। यह रक्षात्मक प्रोग्रामिंग की तरह है - किसी दिन पाने वाले और बसने वाले सहायक हो सकते हैं, और उन्हें बनाने / उपयोग करने में बहुत अधिक खर्च नहीं होता है। इसलिए वे कभी-कभी उपयोगी होते हैं।

व्यवहार में, अधिकांश क्षेत्रों में सरल गेटर्स और सेटर हैं। एक संभावित समाधान इस तरह दिखेगा:

public property String foo;   
a->Foo = b->Foo;

अपडेट: यह अत्यधिक संभावना नहीं है कि संपत्ति का समर्थन जावा 7 या शायद कभी जोड़ा जाएगा। अन्य JVM भाषाएँ जैसे ग्रूवी, स्काला आदि अब इस सुविधा का समर्थन करती हैं। - एलेक्स मिलर


28
यह बहुत बुरा है, मुझे C # -स्टाइल प्रॉपर्टीज़ पसंद हैं (जो आपको कैसी लग रही है)
जॉन ऑनस्टॉट

2
इसलिए ओवरलोडिंग का उपयोग करें ... निजी int _x; public void x (int value) {_x = value; } public int x () {रिटर्न _x; }
गॉर्डन

12
मैं उपयोग करने में सक्षम होना पसंद करता हूं =, जो मेरी राय में कोड को क्लीनर बनाता है।
सविश

6
@ टी-बुल: सिर्फ इसलिए कि आपके पास दो xएस हो सकते हैं जो दो अलग-अलग चीजें हैं, यह एक अच्छा विचार नहीं है। IMHO, यह एक खराब सुझाव है, क्योंकि यह मानव पाठकों द्वारा भ्रम पैदा कर सकता है। मूल सिद्धांत: एक पाठक को दोतरफा मत बनाइए; यह स्पष्ट करें कि आप क्या कह रहे हैं - विभिन्न संस्थाओं के लिए अलग-अलग नामों का उपयोग करें। भले ही अंतर केवल एक अंडरस्कोर को प्रस्तुत करने का हो। संस्थाओं को अलग करने के लिए आसपास के विराम चिह्न पर भरोसा न करें।
टूलमेकरस्टेव

2
@ToolmakerSteve: यह "भ्रम पैदा कर सकता है" सबसे आम और अभी भी सबसे कमजोर तर्क है जब यह कोडिंग हठधर्मिता का बचाव करने की बात आती है (जैसा कि कोडिंग शैली के विपरीत)। हमेशा ऐसा कोई व्यक्ति होता है जो COULD को सबसे सरल चीजों से भ्रमित करता है। आप हमेशा किसी न किसी को शिकायत करते हुए पाएंगे कि उसने जागने और आधे सप्ताह तक कोडिंग करने के बाद गलती की या कुछ इस तरह और फिर भ्रामक कोडिंग शैली को दोष दे रहा है। मैं वह गिनती नहीं होने देता। यह शैली वैध, स्पष्ट है और नाम स्थान को साफ रखती है। इसके अलावा, यहां अलग-अलग इकाइयां नहीं हैं, वहां / एक / इकाई और इसके आसपास कुछ बॉयलरप्लेट कोड हैं।
टी-बुल

290

ऐसा प्रतीत होता है कि कई जावा लोग सन जावा कोडिंग दिशानिर्देशों से परिचित नहीं हैं जो कहते हैं कि सार्वजनिक रूप से चर का उपयोग करना काफी उचित है जब कक्षा अनिवार्य रूप से एक "संरचना" होती है, यदि जावा "संरचना" (जब कोई व्यवहार न हो) का समर्थन करता है।

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

1999 से जावा कोड कन्वेंशन और अभी भी अपरिवर्तित है।

10.1 इंस्टेंस और क्लास वेरिएबल्स तक पहुंच प्रदान करना

अच्छे कारण के बिना किसी भी उदाहरण या वर्ग चर को सार्वजनिक न करें। अक्सर, उदाहरण के चर को स्पष्ट रूप से सेट या प्राप्त करने की आवश्यकता नहीं होती है-अक्सर ऐसा होता है जो विधि कॉल के साइड इफेक्ट के रूप में होता है।

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

http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-137265.html#177

http://en.wikipedia.org/wiki/Plain_old_data_structure

http://docs.oracle.com/javase/1.3/docs/guide/collections/designfaq.html#28


88
+1 वास्तव में एक आधिकारिक स्रोत होने के लिए। हर दूसरे जवाब में लोग अपनी राय रखते हैं जैसे कि वे तथ्य हों।
आर्टऑफवर्फिश

1
जावा बीन्स विनिर्देशन है जो प्राप्त और निर्धारित विधियों का उपयोग करके गुणों तक पहुँचने का एक उद्योग-मानक तरीका है ... अवलोकन के लिए en.wikipedia.org/wiki/JavaBeans देखें ।
user924272

4
@ user924272: जावा बीन्स इस उत्तर के लिए प्रासंगिक कैसे है, जो चर्चा करता है कि "सार्वजनिक उदाहरण चर" का उपयोग करना कब उचित है? यदि कल्पना गुण में स्वचालित रूप से परिवर्तनशील चर का एक मानक तरीका था, तो ए एल सी #, यह प्रासंगिक हो सकता है। लेकिन यह सही नहीं है? यह केवल बॉयलरप्लेट गेटर्स के नामकरण को निर्दिष्ट करता है और बसने वाला होता है जिसे इस तरह की मैपिंग बनाने की आवश्यकता होती है।
टूलमेकरसैट १ '

@ToolmakerSteve। यह एक जावा प्रश्न है। इसके अलावा, सवाल एक आम समस्या के लिए है जहां एक विनिर्देश मौजूद है। एक पुराने स्कूल के दृष्टिकोण से, फील्ड म्यूटेशन को डीबग करना बहुत आसान है, जब इसे करने का एक मानक तरीका है - एक सेटर में एक ब्रेकपॉइंट सेट करें। यह संभवत: आधुनिक डिबगर्स के साथ अप्रचलित कर दिया गया है, फिर भी मैं कक्षाओं में सीधे "पंच" ऑब्जेक्ट्स को फेल करने के लिए मजबूर हूं ... जबकि छोटे अनुप्रयोगों के लिए यह ठीक है, यह बड़े ऐप और बड़े संगठनों के लिए एक वास्तविक सिरदर्द है
user924272

223

सामान्य ज्ञान का उपयोग करें। यदि आपके पास कुछ ऐसा है:

public class ScreenCoord2D{
    public int x;
    public int y;
}

फिर उन्हें गेटर्स और सेटर्स में लपेटने का कोई मतलब नहीं है। आप कभी भी x, y को किसी भी अन्य तरीके से पूरे पिक्सेल में समन्वयित नहीं करने जा रहे हैं। गेटर्स और सेटर केवल आपको धीमा कर देंगे।

दूसरी ओर, साथ:

public class BankAccount{
    public int balance;
}

आप भविष्य में किसी बिंदु पर संतुलन की गणना करने के तरीके को बदलना चाहते हैं। यह वास्तव में गेटर्स और सेटर का उपयोग करना चाहिए।

यह जानना हमेशा बेहतर होता है कि आप अच्छी प्रैक्टिस क्यों कर रहे हैं, ताकि आप जान सकें कि नियमों को मोड़ना कब ठीक है।


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

@SpacenJasset: FYI करें, मैं यह नहीं देखता कि आपके उदाहरण (एकाधिक रिटर्न मान; ध्रुवीय निर्देशांक) सार्वजनिक क्षेत्र बनाम गेट्टर / सेटर का उपयोग करने के लिए कोई असर डालते हैं। कई रिटर्न वैल्यू के मामले में, यह काउंटर-प्रॉडक्टिव भी हो सकता है, क्योंकि यकीनन कॉल करने वाले को केवल रिटर्न वैल्यू हासिल करनी चाहिए, जो पब्लिक गेटर्स और प्राइवेट सेनेटर्स (अपरिवर्तनीय) के पक्ष में तर्क देता है। यह किसी (x, y) ऑब्जेक्ट से ध्रुवीय निर्देशांक वापस करने के लिए भी सही हो सकता है - ACCUMULATIVE गणित त्रुटियों पर विचार करें, क्योंकि ध्रुवीय निर्देशांक के अलग-अलग घटकों में परिवर्तन वापस (x, y) में बदल दिए जाते हैं।
टूलमेकरसेव

@SpacenJasset: लेकिन मैं आपके सिद्धांत से सहमत हूं।
टूलमेकरसैट १ '

1
आप एक वैध बिंदु है, लेकिन मुझे लगता है कि पिक्सल बात की तरह यह सुनिश्चित करने के बाद से एक बुरा उदाहरण पिक्सेल खिड़की (सिर्फ एक उदाहरण) के भीतर है है कुछ है कि किसी को कर सकते हैं, और इसके अलावा, दे किसी को पिक्सेल सेट (-5, -5)हो सकता है नहीं हो एक अच्छा विचार। :-)
होर्से

50

परस्परता संबंधी चिंताओं को दूर करने के लिए आप x और y को अंतिम घोषित कर सकते हैं। उदाहरण के लिए:

class Data {
  public final int x;
  public final int y;
  public Data( int x, int y){
    this.x = x;
    this.y = y;
  }
}

कॉलिंग कोड जो इन फ़ील्ड्स में लिखने का प्रयास करता है, उसे "फ़ील्ड x अंतिम घोषित किए जाने का एक संकलित समय त्रुटि प्राप्त होगी; असाइन नहीं किया जा सकता है"।

क्लाइंट कोड में आपके द्वारा वर्णित 'शॉर्ट-हैंड' सुविधा हो सकती है

public class DataTest {
    public DataTest() {
        Data data1 = new Data(1, 5);
        Data data2 = new Data(2, 4);
        System.out.println(f(data1));
        System.out.println(f(data2));
    }

    public int f(Data d) {
        return (3 * d.x) / d.y;
    }

    public static void main(String[] args) {
        DataTest dataTest = new DataTest();
    }
}

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

@ToolmakerSteve - प्रतिक्रिया के लिए धन्यवाद - बहुत सराहना की।
ब्रायन

मैंने एक अंतिम वर्ग के अंतिम उदाहरणों को संरचना "उदाहरण" के रूप में अंतिम क्षेत्रों के साथ उपयोग करने का प्रयास किया, लेकिन caseइस तरह के उदाहरण क्षेत्र का उल्लेख करते हुए, मुझे मिला Case expressions must be constant expressions। इसके आसपास क्या तरीका है? यहाँ मुहावरेदार अवधारणा क्या है?
n611x007

1
अंतिम फ़ील्ड अभी भी ऑब्जेक्ट्स के संदर्भ हैं, जो स्थिरांक नहीं हैं, क्योंकि जब वे पहली बार उपयोग किए जाते हैं, तो उन्हें प्रारंभ किया जाएगा। संकलक वस्तु संदर्भों के "मूल्य" को नहीं जान सकता है। संकलन करते समय लगातार ज्ञात होना चाहिए।
जोहान टिडेन

1
+1 वास्तव में महत्वपूर्ण उत्तर। अपरिवर्तनीय वर्गों की उपयोगिता को मेरी राय में कम करके नहीं आंका जा सकता। उनके "आग और भूल" शब्दार्थ कोड के बारे में तर्क अक्सर सरल बनाते हैं, विशेष रूप से बहुरंगी वातावरण में, जहां उन्हें थ्रेड के बीच मनमाने ढंग से बिना सिंक्रनाइज़ेशन के साझा किया जा सकता है।
द ओपरेटर

11

publicखेतों का उपयोग न करें

publicजब आप वास्तव में किसी वर्ग के आंतरिक व्यवहार को लपेटना चाहते हैं, तो फ़ील्ड का उपयोग न करें । java.io.BufferedReaderउदाहरण के लिए लें । यह निम्नलिखित क्षेत्र है:

private boolean skipLF = false; // If the next character is a line feed, skip it

skipLFसभी पठन विधियों में पढ़ा और लिखा गया है। क्या होगा यदि एक अलग थ्रेड में चल रहे बाहरी वर्ग ने दुर्भावनापूर्ण रूप skipLFसे एक रीड के बीच में स्थिति को संशोधित किया हो ? BufferedReaderनिश्चित रूप से haywire जाएगा।

publicखेतों का उपयोग करें

इस Pointवर्ग को उदाहरण के लिए लें :

class Point {
    private double x;
    private double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public double getX() {
        return this.x;
    }

    public double getY() {
        return this.y;
    }

    public void setX(double x) {
        this.x = x;
    }

    public void setY(double y) {
        this.y = y;
    }
}

यह लिखने के लिए बहुत दर्दनाक दो बिंदुओं के बीच की दूरी की गणना करेगा।

Point a = new Point(5.0, 4.0);
Point b = new Point(4.0, 9.0);
double distance = Math.sqrt(Math.pow(b.getX() - a.getX(), 2) + Math.pow(b.getY() - a.getY(), 2));

कक्षा में सादे गेटर्स और सेटर के अलावा कोई व्यवहार नहीं है। सार्वजनिक फ़ील्ड का उपयोग करने के लिए यह स्वीकार्य है जब वर्ग सिर्फ एक डेटा संरचना का प्रतिनिधित्व करता है, और उसके पास नहीं है, और कभी भी व्यवहार नहीं होगा (पतले गेटर्स और बसने वालों को यहां व्यवहार नहीं माना जाता है)। इसे इस तरह से बेहतर लिखा जा सकता है:

class Point {
    public double x;
    public double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
}

Point a = new Point(5.0, 4.0);
Point b = new Point(4.0, 9.0);
double distance = Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));

स्वच्छ!

लेकिन याद रखें: न केवल आपके वर्ग को व्यवहार से अनुपस्थित होना चाहिए, बल्कि इसके साथ ही भविष्य में भी व्यवहार का कोई कारण नहीं होना चाहिए ।


(यह वास्तव में क्या है इस उत्तर का वर्णन शब्दों में। "जावा भाषा प्रोग्रामिंग के लिए कोड कन्वेंशनों: 10 प्रोग्रामिंग आचरण" :

उपयुक्त सार्वजनिक उदाहरण चर का एक उदाहरण वह मामला है जहां वर्ग अनिवार्य रूप से डेटा संरचना है, जिसमें कोई व्यवहार नहीं है। दूसरे शब्दों में, यदि आपने structएक वर्ग के बजाय (यदि जावा समर्थित है struct) का उपयोग किया होता, तो यह वर्ग के उदाहरण चर को सार्वजनिक करने के लिए उपयुक्त है।

इसलिए आधिकारिक प्रलेखन भी इस प्रथा को स्वीकार करता है।)


इसके अलावा, अगर आपको अतिरिक्त यकीन है कि उपरोक्त Pointवर्ग के सदस्यों को अपरिवर्तनीय होना चाहिए, तो आप finalइसे लागू करने के लिए कीवर्ड जोड़ सकते हैं :

public final double x;
public final double y;

8

वैसे, जो संरचना आप एक उदाहरण के रूप में दे रहे हैं वह पहले से ही जावा बेस क्लास लाइब्रेरी में मौजूद है java.awt.Point। इसमें सार्वजनिक क्षेत्रों के रूप में x और y है, इसे अपने लिए देखें

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


+1 एक मुद्दे का अच्छा उल्लेख - एक तरीका जिसमें परिणाम अभी भी सी संरचना की तरह नहीं है। हालाँकि, आप जिस मुद्दे के बारे में जावा ऑब्जेक्ट्स को हमेशा संदर्भ से उठाते हैं, वह सार्वजनिक लिखने योग्य क्षेत्र (जो ओपी के प्रश्न का सार है - जिसका उपयोग करने के लिए प्रतिनिधित्व करता है) के बजाय एक सेटर बनाकर सुधार नहीं किया जाता है। बल्कि, यह NEITHER करने के पक्ष में एक तर्क है। यह IMMUTABILITY का तर्क है। जिसे या तो एक public finalक्षेत्र के रूप में किया जा सकता है , जैसा कि ब्रायन के जवाब में, या एक सार्वजनिक गेट्टर के पास है, लेकिन कोई सार्वजनिक सेटर नहीं है। यही है, चाहे कोई फ़ील्ड का उपयोग करता है या एक्सेसर्स सारहीन है।
टूलमेकरसैट

8

पुन: अकू, izb, जॉन टॉपले ...

परिवर्तनशीलता के मुद्दों के लिए बाहर देखो ...

यह गेटर्स / सेटर्स को छोड़ने के लिए समझदार लग सकता है। यह वास्तव में कुछ मामलों में ठीक हो सकता है। यहां दिखाए गए प्रस्तावित पैटर्न के साथ वास्तविक समस्या उत्परिवर्तन है।

समस्या यह है कि आप गैर-अंतिम, सार्वजनिक क्षेत्रों से संबंधित ऑब्जेक्ट संदर्भ पास कर लेते हैं। उस संदर्भ के साथ कुछ भी उन क्षेत्रों को संशोधित करने के लिए स्वतंत्र है। अब उस वस्तु की स्थिति पर आपका कोई नियंत्रण नहीं है। (सोचिए अगर स्ट्रिंग्स परस्पर थे तो क्या होगा।)

यह बुरा हो जाता है जब वह वस्तु दूसरे की आंतरिक स्थिति का एक महत्वपूर्ण हिस्सा है, तो आपने आंतरिक कार्यान्वयन को उजागर किया है। इसे रोकने के लिए, ऑब्जेक्ट की एक प्रति इसके बजाय वापस करनी होगी। यह काम करता है, लेकिन बनाई गई एकल-उपयोग प्रतियों के टन से बड़े पैमाने पर जीसी दबाव पैदा कर सकता है।

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

देखें: " प्रभावी जावा यहोशू बलोच द्वारा " - आइटम # 13: अनुकूलता।

पुनश्च: यह भी ध्यान रखें, यदि संभव हो तो सभी JVM इन दिनों गेटमैथ को दूर कर देंगे, जिसके परिणामस्वरूप केवल एक फ़ील्ड-रीडिंग निर्देश होगा।


12
कैसे एक गेट्टर / सेटर इस मुद्दे को हल करता है। आपके पास अभी भी एक संदर्भ है, आपके पास संचालन के साथ कोई सिंक्रनाइज़ेशन नहीं है। गेटर्स / सेटर्स खुद को और उनमें सुरक्षा प्रदान नहीं करते हैं।
he_the_great

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

7

मैंने कुछ परियोजनाओं में इस सिद्धांत पर कोशिश की है कि गेटर्स और सेटर कोड को शब्दार्थ रूप से अर्थहीन रूप से बँटते हैं, और यह कि अन्य भाषाएँ कॉन्वेंट-बेस्ड डेटा-हाइडिंग या जिम्मेदारियों के विभाजन (जैसे अजगर) के साथ ठीक लगती हैं।

जैसा कि दूसरों ने ऊपर उल्लेख किया है, 2 समस्याएं हैं जो आप में चलते हैं, और वे वास्तव में ठीक नहीं हैं:

  • जावा दुनिया में किसी भी स्वचालित उपकरण के बारे में बस गेट्टर / सेटर कन्वेंशन पर निर्भर करता है। Ditto के लिए, जैसा कि दूसरों द्वारा नोट किया गया है, jsp टैग, स्प्रिंग कॉन्फ़िगरेशन, ग्रहण टूल, आदि आदि ... आपके उपकरण जो देखने की उम्मीद करते हैं उसके खिलाफ लड़ना Google को लंबे समय तक ट्रोल करने के लिए एक नुस्खा है जो उस गैर-मानक तरीके को खोजने की कोशिश कर रहा है। वसंत सेम। वास्तव में परेशानी के लायक नहीं।
  • एक बार जब आपके पास सैंकड़ों सार्वजनिक चर के साथ आपका सुरुचिपूर्ण ढंग से कोडित आवेदन होता है, तो आपको कम से कम एक स्थिति मिलेगी जहां वे अपर्याप्त हैं - जहां आपको बिल्कुल अपरिवर्तनीयता की आवश्यकता होती है, या जब चर सेट हो जाता है, या आपको कुछ घटना को ट्रिगर करने की आवश्यकता होती है, या आप फेंकना चाहते हैं परिवर्तनशील परिवर्तन पर एक अपवाद क्योंकि यह एक वस्तु स्थिति को कुछ अप्रिय बनाता है। फिर आप अपने कोड को अव्यवस्थित करने के बीच असम्भव विकल्पों के साथ अटक जाते हैं, हर जगह चर को सीधे संदर्भित किया जाता है, आपके आवेदन में 1000 चर में से 3 के लिए कुछ विशेष अभिगम प्रपत्र होता है।

और यह पूरी तरह से स्व-निहित निजी परियोजना में काम करने का सबसे अच्छा मामला है। एक बार जब आप पूरी तरह से सार्वजनिक रूप से सुलभ पुस्तकालय में निर्यात करते हैं तो ये समस्याएं और भी बड़ी हो जाएंगी।

जावा बहुत ही क्रियात्मक है, और यह एक लुभावना काम है। यह मत करो।


सार्वजनिक क्षेत्रों की सड़क से नीचे जाने की समस्याओं की उत्कृष्ट चर्चा। जावा की एक निश्चित कमी, जो मुझे तब गुस्सा दिलाती है जब मुझे जावा को C # से वापस स्विच करना पड़ता है (जो जावा की असुविधा से सीखा है)।
टूलमेकरसैट

4

यदि जावा तरीका OO तरीका है, तो हाँ, सार्वजनिक क्षेत्रों के साथ एक वर्ग बनाने से जानकारी छिपाने के आसपास के सिद्धांत टूट जाते हैं जो कहते हैं कि एक वस्तु को अपनी आंतरिक स्थिति का प्रबंधन करना चाहिए। (इसलिए जैसा कि मैं सिर्फ आप पर शब्दजाल नहीं उगल रहा हूं, सूचना छिपाने का एक फायदा यह है कि एक वर्ग के आंतरिक कामकाज एक इंटरफ़ेस के पीछे छिपे हुए हैं - कहते हैं कि आप उस तंत्र को बदलना चाहते थे जिसके द्वारा आपके संरचनात्मक वर्ग ने अपने खेतों में से एक को बचाया, आपको शायद वापस जाने और वर्ग का उपयोग करने वाले किसी भी वर्ग को बदलने की आवश्यकता होगी ...)

आप जावाबिन नामकरण के अनुरूप वर्गों के लिए समर्थन का लाभ नहीं उठा सकते हैं, जो कि अगर आप निर्णय लेते हैं, तो कहेंगे, एक जावास्वर पेज में कक्षा का उपयोग करें जो अभिव्यक्ति भाषा का उपयोग करके लिखा गया है।

JavaWorld लेख क्यों गेट्टर और सेटर विधियां ईविल हैं लेख हैं, यह सोचने में भी आपकी रुचि हो सकती है कि एक्सेसर और म्यूटेटर विधियों को लागू करने के लिए कब नहीं।

यदि आप एक छोटा सा समाधान लिख रहे हैं और शामिल कोड की मात्रा को कम करना चाहते हैं, तो जावा तरीका सही तरीका नहीं हो सकता है - मुझे लगता है कि यह हमेशा आप पर निर्भर करता है और जिस समस्या को आप हल करने की कोशिश कर रहे हैं।


1
लेख "क्यों गेट्टर और सेटर विधियां ईविल हैं" के लिंक के लिए +1। हालाँकि, आपका उत्तर स्पष्ट हो जाता अगर आप बताते हैं कि दोनों सार्वजनिक क्षेत्र और सार्वजनिक गेटटर / सेटर एक्वायली नहीं हैं तो जावा तरीका: जैसा कि उस लेख में बताया गया है - जब संभव हो, तो या तो मत करो। इसके बजाय, क्लाइंट को उन तरीकों से विशिष्ट तरीके प्रदान करें जो उन्हें करने की आवश्यकता है, बजाय उदाहरण के आंतरिक प्रतिनिधित्व को प्रतिबिंबित करने के। फिर भी, यह वास्तव में पूछे जाने वाले प्रश्न को संबोधित नहीं करता है (जो कि "सरल" संरचना "मामले के लिए उपयोग किया जाता है), जिसे डेवलपर द्वारा बेहतर उत्तर दिया गया है। आईजीबी, और ब्रायन।
टूलमेकरस्टेव

3

उस प्रकार के कोड में कुछ भी गलत नहीं है, बशर्ते कि लेखक जानता हो कि वे वस्तुओं के बजाय संरचना (या डेटा शटल्स) हैं। जावा डेवलपर्स के बहुत सारे एक अच्छी तरह से बनाई गई वस्तु के बीच अंतर नहीं बता सकते हैं (न केवल java.lang.Object का एक उपवर्ग, लेकिन एक विशिष्ट डोमेन में एक सच्ची वस्तु) और एक अनानास। एर्गो, वे वस्तुओं और वाइसवेरा की आवश्यकता होने पर लेखन संरचना को समाप्त करते हैं।


अनानास मुझे हँसाता है :)
गिलोय

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

यह अंतर के बारे में कुछ नहीं कहता है क्योंकि वे लेखक अंतर के बारे में जानते हैं (वह जानता है कि एक संरचना जैसी इकाई क्या है)। लेखक पूछ रहा है कि क्या किसी OO भाषा में स्ट्रक्चर्स का उपयोग करना उचित है, और मैं कहता हूं कि हाँ (समस्या डोमेन के आधार पर।) यदि यह प्रश्न था कि किसी ऑब्जेक्ट को वास्तविक डोमेन ऑब्जेक्ट क्या बनाता है, तो आपके पास खड़े होने के लिए एक पैर होगा। बहस।
luis.espinal

इसके अलावा, अकुशल डेवलपर का एकमात्र प्रकार जिसे अंतर नहीं पता होना चाहिए वह वह है जो अभी भी स्कूल में है। यह अत्यंत मौलिक है, जैसे किसी लिंक की गई सूची और हैश टेबल के बीच अंतर जानना। यदि कोई व्यक्ति 4 साल की सॉफ्टवेयर डिग्री के साथ स्नातक है, जो यह जानता है कि एक सच्ची वस्तु क्या है, तो या तो वह व्यक्ति इस करियर के लिए नहीं कटता है, या उसे स्कूल वापस जाना चाहिए और धन वापसी की मांग करनी चाहिए। मैं गंभीर हूँ।
luis.espinal

लेकिन आपकी शिकायत को पूरा करने के लिए मैं एक उत्तर दूंगा (जिसका मूल प्रश्न से कोई लेना-देना नहीं है और जो अपने स्वयं के धागे का हकदार है)। वस्तुओं का व्यवहार होता है और राज्य को घेरता है। संरचनाएं नहीं हैं। वस्तुएं राज्य मशीनें हैं। संरचनाएं केवल डेटा एकत्र करने के लिए हैं। यदि लोग अधिक विस्तृत उत्तर चाहते हैं, तो वे एक नया प्रश्न बनाने के लिए स्वतंत्र हैं जहां हम अपने दिल की सामग्री के लिए उस पर विस्तार कर सकते हैं।
luis.espinal

2

सार्वजनिक क्षेत्र के उपयोग के साथ समस्या फ़ैक्टरी विधि के बजाय नए का उपयोग करने के रूप में एक ही समस्या है - यदि आप बाद में अपना विचार बदलते हैं, तो सभी मौजूदा कॉलर टूट गए हैं। इसलिए, एपीआई विकास के दृष्टिकोण से, यह आमतौर पर बुलेट को काटने और गेटर्स / सेटर का उपयोग करने के लिए एक अच्छा विचार है।

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

वैसे, ई-बार्टेक के दावे पर, यह आईएमओ की अत्यधिक संभावना नहीं है कि जावा 7 में संपत्ति का समर्थन जोड़ा जाएगा।


1
यह सच है, लेकिन अगर आप जावा का उपयोग कर रहे हैं तो यह चिंता की बात नहीं है, क्योंकि आप एक क्लिक में पूरे कोड-बेस को रिफलेक्टर कर सकते हैं (एक्लिप्स, नेटबीन्स, शायद वीआईएम और एमएसीएस भी)। यदि आपने अपने किसी गतिशील मित्र को चुना है, जैसे कि ग्रूवी, यहां तक ​​कि एक साधारण एनकैप्सुलेशन भी आपको घंटों या दिनों के लिए ठीक कर सकता है। सौभाग्य से आपके पास आपके परीक्षण मामले होंगे जो आपको सूचित करेंगे ... आपको कितना अधिक कोड ठीक करना होगा।
दान रोसेनस्टार्क

2
आप निश्चित रूप से मानते हैं कि सभी उपयोगकर्ता आपके कोड आधार में हैं, लेकिन निश्चित रूप से, यह अक्सर सच नहीं है। अक्सर विभिन्न गैर-तकनीकी कारणों से कोड बदलना संभव नहीं होता है जो आपके अपने कोड बेस में हो सकता है।
एलेक्स मिलर

2

मैं अपने कोड को सरल बनाने के लिए अक्सर निजी आंतरिक कक्षाओं का निर्माण करते समय इस पैटर्न का उपयोग करता हूं, लेकिन मैं सार्वजनिक एपीआई में ऐसी वस्तुओं को उजागर करने की सिफारिश नहीं करूंगा। सामान्य तौर पर, जितनी अधिक बार आप अपने सार्वजनिक एपीआई में वस्तुओं को बेहतर बना सकते हैं उतना ही बेहतर हो सकता है, और एक अपरिवर्तनीय तरीके से अपनी 'संरचना जैसी' वस्तु का निर्माण संभव नहीं है।

एक तरफ के रूप में, भले ही मैं एक निजी आंतरिक वर्ग के रूप में इस ऑब्जेक्ट को लिख रहा था, फिर भी मैं ऑब्जेक्ट को इनिशियलाइज़ करने के लिए कोड को सरल बनाने के लिए एक कंस्ट्रक्टर प्रदान करूंगा। एक प्रयोग करने योग्य वस्तु को प्राप्त करने के लिए कोड की 3 पंक्तियाँ होने से कोई गड़बड़ हो जाएगी।


2

एक बहुत पुराना सवाल है, लेकिन मुझे एक और छोटा योगदान देना चाहिए। जावा 8 ने लैम्ब्डा एक्सप्रेशन और विधि संदर्भ पेश किए। लैम्ब्डा भाव सरल विधि संदर्भ हो सकते हैं और "सच्चे" शरीर की घोषणा नहीं करते हैं। लेकिन आप किसी फ़ील्ड को विधि संदर्भ में "परिवर्तित" नहीं कर सकते। इस प्रकार

stream.mapToInt(SomeData1::x)

कानूनी नहीं है, लेकिन

stream.mapToInt(SomeData2::getX)

है।


इस मामले में आप उपयोग कर सकते हैं data -> data.x, जो अभी भी उचित है
जेम्स क्रस

1

यदि आपको पता है कि यह हमेशा एक सरल संरचना होने जा रहा है, तो आपको नुकसान नहीं होता है और आप इसे व्यवहार में शामिल नहीं करना चाहते हैं।


1

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


1

यहां मैं 5 अलग-अलग व्यक्तियों के नाम और आयु के इनपुट का कार्यक्रम बनाता हूं और चयन प्रकार (आयु वार) करता हूं। मैंने एक वर्ग का उपयोग किया, जो एक संरचना के रूप में कार्य करता है (जैसे सी प्रोग्रामिंग भाषा) और पूर्ण संचालन करने के लिए एक मुख्य वर्ग। यहाँ मैं कोड प्रस्तुत कर रहा हूँ ...

import java.io.*;

class NameList {
    String name;
    int age;
}

class StructNameAge {
    public static void main(String [] args) throws IOException {

        NameList nl[]=new NameList[5]; // Create new radix of the structure NameList into 'nl' object
        NameList temp=new NameList(); // Create a temporary object of the structure

        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

        /* Enter data into each radix of 'nl' object */

        for(int i=0; i<5; i++) {
            nl[i]=new NameList(); // Assign the structure into each radix

            System.out.print("Name: ");
            nl[i].name=br.readLine();

            System.out.print("Age: ");
            nl[i].age=Integer.parseInt(br.readLine());

            System.out.println();
        }

        /* Perform the sort (Selection Sort Method) */

        for(int i=0; i<4; i++) {
            for(int j=i+1; j<5; j++) {
                if(nl[i].age>nl[j].age) {
                    temp=nl[i];
                    nl[i]=nl[j];
                    nl[j]=temp;
                }
            }
        }

        /* Print each radix stored in 'nl' object */

        for(int i=0; i<5; i++)
            System.out.println(nl[i].name+" ("+nl[i].age+")");
    }
}

उपरोक्त कोड त्रुटि मुक्त और परीक्षण किया गया है ... बस कॉपी करें और इसे अपने आईडीई में पेस्ट करें और ... आप जानते हैं और क्या ??? :)


0

आप सार्वजनिक क्षेत्रों और जावा में कोई विधि नहीं के साथ एक साधारण वर्ग बना सकते हैं, लेकिन यह अभी भी एक वर्ग है और अभी भी एक वर्ग की तरह वाक्यविन्यास और स्मृति आवंटन के मामले में संभाला जाता है। जावा में वास्तव में संरचनाओं को पुन: उत्पन्न करने का कोई तरीका नहीं है।


0

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


0

ज्यादातर चीजों के साथ, सामान्य नियम है और फिर विशिष्ट परिस्थितियां हैं। यदि आप एक बंद, कैप्चर किए गए एप्लिकेशन को कर रहे हैं ताकि आप जान सकें कि किसी दिए गए ऑब्जेक्ट का उपयोग कैसे किया जा रहा है, तो आप दृश्यता और / या दक्षता के पक्ष में अधिक स्वतंत्रता का उपयोग कर सकते हैं। यदि आप एक ऐसा वर्ग विकसित कर रहे हैं जो आपके नियंत्रण से परे दूसरों द्वारा सार्वजनिक रूप से उपयोग किया जा रहा है, तो गेट्टर / सेटर मॉडल की ओर झुकें। सभी चीजों के साथ, बस सामान्य ज्ञान का उपयोग करें। सार्वजनिक रूप से शुरुआती दौर में ऐसा करना ठीक है और फिर बाद में उन्हें बदलने के लिए उन्हें बदल दिया जाए।


0

आस्पेक्ट-ओरिएंटेड प्रोग्रामिंग से आप असाइनमेंट या भ्रूणों को फँसा सकते हैं और उन्हें इंटरसेप्टिंग लॉजिक अटैच कर सकते हैं, जो मैं प्रस्तावित करता हूं कि समस्या को हल करने का सही तरीका है। (इस बात का मुद्दा कि उन्हें सार्वजनिक होना चाहिए या संरक्षित या पैकेज-संरक्षित ऑर्थोगोनल है।)

इस प्रकार आप सही पहुंच वाले क्वालीफायर के साथ निर्बाध क्षेत्रों से शुरू करते हैं। जैसे-जैसे आपके कार्यक्रम की आवश्यकताएं बढ़ती हैं, आप तर्क को संभवतः मान्य करने के लिए संलग्न करते हैं, वापस आ रही वस्तु की एक प्रति बनाते हैं, आदि।

गेटटर / सेटर दर्शन बड़ी संख्या में सरल मामलों पर लागत लगाता है जहां उनकी आवश्यकता नहीं होती है।

पहलू-शैली क्लीनर है या नहीं, कुछ गुणात्मक है। मुझे कक्षा में बस चर देखना आसान होगा और तर्क को अलग से देखना होगा। वास्तव में, एपेट-ओरिएंटेड प्रोग्रामिंग के लिए राइसन डीट्रे यह है कि कई चिंताएं क्रॉस-कटिंग हैं और उन्हें क्लास बॉडी में कंपार्टमेंटलाइज़ करना स्वयं ही आदर्श नहीं है (उदाहरण के लिए लॉगिंग होना - यदि आप लॉग इन करना चाहते हैं तो जावा आपको चाहता है। गेटर्स का एक पूरा गुच्छा लिखें और उन्हें सिंक में रखें लेकिन AspectJ आपको एक-लाइनर की अनुमति देता है)।

आईडीई का मुद्दा एक रेड-हेरिंग है। यह इतना अधिक टाइपिंग नहीं है क्योंकि यह रीडिंग और विज़ुअल प्रदूषण है जो गेट / सेट से उत्पन्न होता है।

एनोटेशन पहली नजर में पहलू-उन्मुख प्रोग्रामिंग के समान लगते हैं, हालांकि आपको एंपेक्टज में एक संक्षिप्त वाइल्ड-कार्ड-जैसे पॉइंटकट स्पेसिफिकेशन के विपरीत, एनोटेशन संलग्न करके आपको थकाऊ रूप से शानदार शॉर्टकट की आवश्यकता होती है।

मुझे आशा है कि AspectJ के बारे में जागरूकता लोगों को समय से पहले गतिशील भाषाओं पर बसने से रोकती है।

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