स्थैतिक तरीकों को ओवरराइड करना क्यों संभव नहीं है?
यदि संभव हो, तो कृपया एक उदाहरण का उपयोग करें।
Parent p = new Child()
और फिर p.childOverriddenStaticMethod()
संकलक इसे Parent.childOverriddenStaticMethod()
संदर्भ प्रकार को देखकर हल करेगा ।
स्थैतिक तरीकों को ओवरराइड करना क्यों संभव नहीं है?
यदि संभव हो, तो कृपया एक उदाहरण का उपयोग करें।
Parent p = new Child()
और फिर p.childOverriddenStaticMethod()
संकलक इसे Parent.childOverriddenStaticMethod()
संदर्भ प्रकार को देखकर हल करेगा ।
जवाबों:
ओवरराइडिंग एक वर्ग की आवृत्ति पर निर्भर करता है। बहुरूपता की बात यह है कि आप एक वर्ग को उपवर्गित कर सकते हैं और उन उपवर्गों को लागू करने वाली वस्तुओं में सुपरक्लास में परिभाषित समान विधियों (और उपवर्गों में ओवरराइड) के लिए अलग-अलग व्यवहार होंगे। एक स्थिर विधि किसी भी वर्ग के उदाहरण के साथ संबद्ध नहीं है इसलिए अवधारणा लागू नहीं है।
जावा के डिजाइन को चलाने वाले दो विचार थे जिन्होंने इस पर प्रभाव डाला। एक प्रदर्शन के साथ एक चिंता का विषय था: स्मॉलटाक की बहुत आलोचना हुई थी, क्योंकि यह बहुत धीमा था (कचरा संग्रह और पॉलीमॉर्फिक कॉल उस का हिस्सा था) और जावा के निर्माता इससे बचने के लिए दृढ़ थे। एक अन्य निर्णय यह था कि जावा के लिए लक्षित दर्शक C ++ डेवलपर्स थे। स्टैटिक मेथड्स उस तरह से काम करते हैं जिससे उन्हें C ++ प्रोग्रामर्स के लिए परिचित होने का लाभ मिलता है और यह बहुत तेज़ भी था, क्योंकि रनटाइम तक यह पता करने की कोई ज़रूरत नहीं है कि किस विधि को कॉल करना है।
objects
) के बराबर तरीकों की ओवरलोडिंग की अनुमति देता है।
obj.staticMethod()
) से एक स्थिर विधि को कॉल किया जाता है - जिसे अनुमति दी जाती है और संकलन-समय प्रकारों का उपयोग किया जाता है। जब स्थिर कॉल किसी वर्ग की गैर-स्थिर पद्धति में होता है, तो "वर्तमान" ऑब्जेक्ट एक प्रकार का वर्ग हो सकता है - लेकिन व्युत्पन्न प्रकारों पर परिभाषित स्थिर तरीकों को नहीं माना जाता है (वे रन-टाइम प्रकार में हैं पदानुक्रम)।
व्यक्तिगत रूप से मुझे लगता है कि यह जावा के डिजाइन में एक दोष है। हां, हां, मैं समझता हूं कि गैर-स्टैटिक विधियाँ एक उदाहरण से जुड़ी होती हैं जबकि स्टैटिक विधियाँ किसी वर्ग आदि से जुड़ी होती हैं। फिर भी, निम्नलिखित कोड पर विचार करें:
public class RegularEmployee {
private BigDecimal salary;
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".02");
}
public BigDecimal calculateBonus() {
return salary.multiply(getBonusMultiplier());
}
/* ... presumably lots of other code ... */
}
public class SpecialEmployee extends RegularEmployee {
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".03");
}
}
यह कोड काम नहीं करेगा जैसा कि आप उम्मीद कर सकते हैं। अर्थात्, विशेष कर्मचारी को नियमित कर्मचारियों की तरह 2% बोनस मिलता है। लेकिन अगर आप "स्टैटिक" को हटाते हैं, तो स्पेशलइम्प्लॉई को 3% बोनस मिलता है।
(निश्चित रूप से, यह उदाहरण खराब कोडिंग शैली है कि वास्तविक जीवन में आप शायद बोनस गुणक को हार्ड-कोडेड के बजाय एक डेटाबेस में कहीं और चाहते हैं। लेकिन ऐसा सिर्फ इसलिए है क्योंकि मैं उदाहरण को बहुत अधिक नहीं समझना चाहता था। बिंदु के लिए अप्रासंगिक का कोड।)
यह मेरे लिए काफी प्रशंसनीय है कि आप getBonusMultiplier को स्टैटिक बनाना चाहते हैं। शायद आप प्रत्येक श्रेणी में एक कर्मचारी की आवश्यकता के बिना, सभी श्रेणियों के कर्मचारियों के लिए बोनस गुणक प्रदर्शित करने में सक्षम होना चाहते हैं। ऐसे उदाहरण उदाहरणों की खोज करने का क्या मतलब होगा? क्या होगा अगर हम कर्मचारी की एक नई श्रेणी बना रहे हैं और उसके पास अभी तक कोई कर्मचारी नहीं है? यह तार्किक रूप से एक स्थिर कार्य है।
लेकिन यह काम नहीं करता है।
और हाँ, हाँ, मैं इसे काम करने के लिए उपरोक्त कोड को फिर से लिखने के किसी भी तरीके के बारे में सोच सकता हूं। मेरा कहना यह नहीं है कि यह एक असम्भव समस्या पैदा करता है, लेकिन यह अलिखित प्रोग्रामर के लिए एक जाल बनाता है, क्योंकि भाषा वैसा व्यवहार नहीं करती जैसा कि मुझे लगता है कि एक उचित व्यक्ति उम्मीद करेगा।
शायद अगर मैंने एक ओओपी भाषा के लिए एक कंपाइलर लिखने की कोशिश की, तो मैं जल्दी से देखूंगा कि इसे क्यों लागू किया जाए ताकि स्थिर कार्यों को ओवरराइड किया जा सके यह मुश्किल या असंभव होगा।
या शायद कुछ अच्छे कारण है कि जावा इस तरह से व्यवहार करता है। क्या कोई इस व्यवहार का लाभ उठा सकता है, समस्या की कोई श्रेणी जिसे इसके द्वारा आसान बनाया गया है? मेरा मतलब है, मुझे सिर्फ जावा लैंग्वेज स्पेक की ओर इशारा न करें और कहें "देखें, यह प्रलेखित है कि यह कैसे व्यवहार करता है"। मुझे पता है। लेकिन क्या एक अच्छा कारण है कि वह इस तरह से व्यवहार करे? (स्पष्ट के अलावा "यह सही काम करना मुश्किल था" ...)
अपडेट करें
@VicKirk: यदि आपका मतलब है कि यह "खराब डिज़ाइन" है, क्योंकि यह फिट नहीं है कि जावा स्टेटिक्स को कैसे संभालता है, तो मेरा जवाब है, "ठीक है, दुआ, बिल्कुल।" जैसा कि मैंने अपने मूल पोस्ट में कहा था, यह काम नहीं करता है। लेकिन अगर आपका मतलब यह है कि यह इस अर्थ में खराब डिज़ाइन है कि जहां यह काम किया गया है, वहां एक ऐसी भाषा के साथ कुछ गलत होगा, जहां स्टैटिक्स को वर्चुअल फ़ंक्शंस की तरह ही ओवरराइड किया जा सकता है, तो यह किसी तरह एक अस्पष्टता का परिचय देगा या यह असंभव होगा। कुशलता से लागू करें या कुछ इस तरह, मैं जवाब देता हूं, "क्यों? अवधारणा के साथ क्या गलत है?"
मुझे लगता है कि मैं जो उदाहरण देता हूं, वह बहुत स्वाभाविक बात है कि मैं क्या करना चाहता हूं। मेरे पास एक वर्ग है जो एक फ़ंक्शन है जो किसी भी उदाहरण डेटा पर निर्भर नहीं करता है, और जिसे मैं बहुत ही उचित रूप से एक उदाहरण से स्वतंत्र कॉल करना चाहता हूं, साथ ही एक इंस्टेंस विधि से कॉल करना चाहता हूं। यह काम क्यों नहीं करना चाहिए? मैंने इस स्थिति में वर्षों में कई बार भाग लिया है। व्यवहार में मैं फ़ंक्शन को आभासी बनाकर इसके चारों ओर मिलता हूं, और फिर एक स्थिर विधि बनाता हूं जिसका जीवन में एकमात्र उद्देश्य एक स्थिर विधि है जो कॉल को वर्चुअल विधि से एक डमी उदाहरण के साथ पास करता है। जो वहां पहुंचने के लिए एक बहुत ही गोल चक्कर की तरह लगता है।
someStatic()
और B का विस्तार A से है, तो A में विधि से B.someMethod()
बंध जाता है। यदि मैं बाद someStatic()
में B को जोड़ देता हूं , तो कॉलिंग कोड को A.someStatic()
फिर से जमा करने तक कॉलिंग कोड अभी भी इनवॉइस करता है । यह भी मुझे आश्चर्यचकित bInstance.someStatic()
करता है कि घोषित प्रकार के इनस्टांस का उपयोग करता है , न कि रनटाइम प्रकार का क्योंकि यह संकलन नहीं लिंक पर बांधता है, इसलिए A bInstance; ... bInstance.someStatic()
ए.सोमैस्टैटिक () यदि बी.सोमस्टैटिक () मौजूद है , तो आह्वान करता है।
संक्षिप्त उत्तर है: यह पूरी तरह से संभव है, लेकिन जावा ऐसा नहीं करता है।
यहां कुछ कोड दिए गए हैं जो वर्तमान स्थिति को दर्शाते हैं जावा में :
फ़ाइल Base.java
:
package sp.trial;
public class Base {
static void printValue() {
System.out.println(" Called static Base method.");
}
void nonStatPrintValue() {
System.out.println(" Called non-static Base method.");
}
void nonLocalIndirectStatMethod() {
System.out.println(" Non-static calls overridden(?) static:");
System.out.print(" ");
this.printValue();
}
}
फ़ाइल Child.java
:
package sp.trial;
public class Child extends Base {
static void printValue() {
System.out.println(" Called static Child method.");
}
void nonStatPrintValue() {
System.out.println(" Called non-static Child method.");
}
void localIndirectStatMethod() {
System.out.println(" Non-static calls own static:");
System.out.print(" ");
printValue();
}
public static void main(String[] args) {
System.out.println("Object: static type Base; runtime type Child:");
Base base = new Child();
base.printValue();
base.nonStatPrintValue();
System.out.println("Object: static type Child; runtime type Child:");
Child child = new Child();
child.printValue();
child.nonStatPrintValue();
System.out.println("Class: Child static call:");
Child.printValue();
System.out.println("Class: Base static call:");
Base.printValue();
System.out.println("Object: static/runtime type Child -- call static from non-static method of Child:");
child.localIndirectStatMethod();
System.out.println("Object: static/runtime type Child -- call static from non-static method of Base:");
child.nonLocalIndirectStatMethod();
}
}
यदि आप इसे चलाते हैं (मैंने इसे मैक पर किया था, ग्रहण से, जावा 1.6 का उपयोग करके) आपको मिलता है:
Object: static type Base; runtime type Child.
Called static Base method.
Called non-static Child method.
Object: static type Child; runtime type Child.
Called static Child method.
Called non-static Child method.
Class: Child static call.
Called static Child method.
Class: Base static call.
Called static Base method.
Object: static/runtime type Child -- call static from non-static method of Child.
Non-static calls own static.
Called static Child method.
Object: static/runtime type Child -- call static from non-static method of Base.
Non-static calls overridden(?) static.
Called static Base method.
यहाँ, केवल वे मामले जो आश्चर्यचकित कर सकते हैं (और जो प्रश्न के बारे में है) पहला मामला प्रतीत होता है :
"रन-टाइम प्रकार का उपयोग यह निर्धारित करने के लिए नहीं किया जाता है कि कौन से स्थिर तरीके कहलाते हैं, यहां तक कि जब ऑब्जेक्ट ऑब्जेक्ट ( obj.staticMethod()
) के साथ कहा जाता है ।"
और अंतिम मामला:
"जब किसी क्लास के ऑब्जेक्ट मेथड से स्टैटिक मेथड को कॉल किया जाता है, तो जो स्टैटिक मेथड चुना जाता है वह क्लास से ही ऐक्सेस होता है ना कि क्लास से ऑब्जेक्ट के रन-टाइम टाइप को डिफाइन करता है।"
स्थिर कॉल को संकलन-समय पर हल किया जाता है, जबकि रन-टाइम में एक गैर-स्थिर पद्धति कॉल को हल किया जाता है। ध्यान दें कि यद्यपि स्थैतिक विधियाँ विरासत में मिली हैं (अभिभावक से) उन्हें अधिभूत नहीं किया गया है (बच्चे द्वारा) जाता है। यदि आप अन्यथा की उम्मीद करते हैं तो यह आश्चर्य की बात हो सकती है।
रन-टाइम प्रकार का उपयोग करके ऑब्जेक्ट विधि कॉल का समाधान किया जाता है, लेकिन स्टैटिक ( क्लास ) विधि कॉल का संकलन-समय (घोषित) प्रकार का उपयोग करके हल किया जाता है।
इन नियमों को बदलने के लिए, ताकि अंतिम उदाहरण में कॉल किया जा सके Child.printValue()
, स्टैटिक कॉल को रन-टाइम पर एक प्रकार के साथ प्रदान करना होगा, बजाय संकलक के ऑब्जेक्ट के घोषित वर्ग के साथ संकलन-समय पर कॉल को हल करना (या संदर्भ)। स्टैटिक कॉल तब कॉल को हल करने के लिए (डायनामिक) प्रकार पदानुक्रम का उपयोग कर सकते थे, जैसे कि ऑब्जेक्ट मेथड कॉल आज करते हैं।
यह आसानी से संभव होगा (यदि हमने जावा: -ओ को बदल दिया है), और यह अनुचित नहीं है, हालांकि, इसके कुछ दिलचस्प विचार हैं।
मुख्य विचार यह है कि हमें यह तय करने की आवश्यकता है कि कौन सी स्थिर विधि कॉल को ऐसा करना चाहिए।
फिलहाल, जावा में यह "quirk" भाषा है जिसमें obj.staticMethod()
कॉल को ObjectClass.staticMethod()
कॉल द्वारा प्रतिस्थापित किया जाता है (आमतौर पर एक चेतावनी के साथ)। [ नोट: ObjectClass
संकलन-समय का प्रकार है obj
।] इस तरह से ओवरराइड करने के लिए अच्छे उम्मीदवार होंगे, जो रन-टाइम प्रकार का है obj
।
अगर हमने ऐसा किया है तो यह विधि निकायों को पढ़ने के लिए कठिन बना देगा: माता-पिता वर्ग में स्थिर कॉल संभवतः गतिशील रूप से "पुन: रूट किए गए" हो सकते हैं। इससे बचने के लिए हमें स्टैटिक विधि को एक क्लास नाम के साथ कॉल करना होगा - और इससे कॉल्स को स्पष्ट रूप से कंपाइल-टाइम टाइप पदानुक्रम (अब) के साथ हल किया जाता है।
स्थैतिक विधि को लागू करने के अन्य तरीके अधिक मुश्किल हैं: this.staticMethod()
इसका मतलब उसी तरह होना चाहिए obj.staticMethod()
, जैसे कि रन-टाइम प्रकार this
। हालांकि, इससे मौजूदा कार्यक्रमों के साथ कुछ सिरदर्द हो सकते हैं, जो सजावट के बिना (जाहिरा तौर पर स्थानीय) स्थिर तरीकों को कॉल करते हैं (जो यकीनन इसके बराबर है this.method()
)।
तो अनजाने कॉल के बारे में क्या staticMethod()
? मेरा सुझाव है कि वे आज की तरह ही करें, और स्थानीय वर्ग के संदर्भ का उपयोग करके यह तय करें कि क्या करना है। अन्यथा बहुत भ्रम पैदा होता। बेशक इसका मतलब यह है कि अगर कोई गैर-स्थैतिक विधि थी, और अगर एक स्थैतिक विधि थी, तो method()
इसका मतलब होगा । यह भ्रम का एक और स्रोत है।this.method()
method
ThisClass.method()
method
यदि हमने इस व्यवहार को बदल दिया (और स्थैतिक रूप से गतिशील रूप से गैर-स्थानीय कॉल किया गया), तो हम शायद इसका अर्थ फिर से समझना चाहेंगे final
, private
और protected
क्वालिफायर के रूप में पर static
एक वर्ग के तरीके। हम तो सब तथ्य यह है कि करने के लिए इस्तेमाल करने के लिए होता है private static
और public final
तरीकों ओवरराइड नहीं कर रहे हैं, और इसलिए सुरक्षित रूप से संकलन समय पर हल किया जा सकता है, और "सुरक्षित" स्थानीय संदर्भ के रूप में पढ़ने के लिए कर रहे हैं।
दरअसल हम गलत थे।
जावा के बावजूद आप डिफ़ॉल्ट रूप से स्थिर तरीकों को ओवरराइड करने की अनुमति नहीं देते हैं, यदि आप जावा में क्लास और मेथड क्लासेस के प्रलेखन के माध्यम से अच्छी तरह से देखते हैं, तो आप अभी भी वर्कअराउंड का पालन करके स्थैतिक तरीकों का अनुकरण करने का एक तरीका पा सकते हैं:
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
class RegularEmployee {
private BigDecimal salary = BigDecimal.ONE;
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".02");
}
public BigDecimal calculateBonus() {
return salary.multiply(this.getBonusMultiplier());
}
public BigDecimal calculateOverridenBonus() {
try {
// System.out.println(this.getClass().getDeclaredMethod(
// "getBonusMultiplier").toString());
try {
return salary.multiply((BigDecimal) this.getClass()
.getDeclaredMethod("getBonusMultiplier").invoke(this));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
return null;
}
// ... presumably lots of other code ...
}
final class SpecialEmployee extends RegularEmployee {
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".03");
}
}
public class StaticTestCoolMain {
static public void main(String[] args) {
RegularEmployee Alan = new RegularEmployee();
System.out.println(Alan.calculateBonus());
System.out.println(Alan.calculateOverridenBonus());
SpecialEmployee Bob = new SpecialEmployee();
System.out.println(Bob.calculateBonus());
System.out.println(Bob.calculateOverridenBonus());
}
}
परिणामी उत्पादन:
0.02
0.02
0.02
0.03
हम क्या हासिल करने की कोशिश कर रहे थे :)
भले ही हम तीसरे वेरिएबल कार्ल को रेग्युलर एम्प्लॉई घोषित करते हैं और उसे स्पेशल इम्प्लॉई का उदाहरण देते हैं, फिर भी हमारे पास रेग्युलर इम्प्लॉई का पहला कॉल होगा और दूसरे मामले में स्पेशल इम्प्लॉई का कॉल आएगा।
RegularEmployee Carl = new SpecialEmployee();
System.out.println(Carl.calculateBonus());
System.out.println(Carl.calculateOverridenBonus());
बस आउटपुट कंसोल को देखें:
0.02
0.03
;)
JVM द्वारा स्टैटिक विधियों को वैश्विक माना जाता है, वहाँ वस्तु उदाहरण के लिए बाध्य नहीं हैं।
यह वैचारिक रूप से संभव हो सकता है यदि आप क्लास ऑब्जेक्ट्स (जैसे कि स्मॉलटॉक जैसी भाषाओं) से स्थिर तरीकों को कॉल कर सकते हैं लेकिन यह जावा में ऐसा नहीं है।
संपादित करें
आप स्थैतिक विधि को ओवरलोड कर सकते हैं , यह ठीक है। लेकिन आप एक स्थिर विधि को ओवरराइड नहीं कर सकते , क्योंकि क्लास कोई प्रथम श्रेणी की वस्तु नहीं है। आप रन-टाइम में किसी ऑब्जेक्ट की क्लास लेने के लिए रिफ्लेक्शन का उपयोग कर सकते हैं, लेकिन जो ऑब्जेक्ट आपको मिलता है, वह क्लास पदानुक्रम को समानांतर नहीं करता है।
class MyClass { ... }
class MySubClass extends MyClass { ... }
MyClass obj1 = new MyClass();
MySubClass obj2 = new MySubClass();
ob2 instanceof MyClass --> true
Class clazz1 = obj1.getClass();
Class clazz2 = obj2.getClass();
clazz2 instanceof clazz1 --> false
आप कक्षाओं पर प्रतिबिंबित कर सकते हैं, लेकिन यह वहां रुक जाता है। आप एक स्थिर विधि का उपयोग करके clazz1.staticMethod()
, लेकिन उपयोग नहीं करते हैं MyClass.staticMethod()
। एक स्थैतिक विधि किसी वस्तु से बंधी नहीं होती है और इसलिए this
न ही कोई धारणा होती हैsuper
एक स्थिर विधि में। एक स्थिर विधि एक वैश्विक कार्य है; इसके परिणामस्वरूप बहुरूपता की भी कोई धारणा नहीं है और इसलिए, विधि अधिभावी का कोई मतलब नहीं है।
लेकिन यह संभव हो सकता है यदि MyClass
रन-टाइम पर एक ऑब्जेक्ट था, जिस पर आप एक विधि लागू करते हैं, जैसा कि स्मॉलटाक में (या शायद एक टिप्पणी के रूप में JRuby, लेकिन मुझे JRuby का कुछ भी पता नहीं है)।
अरे, एक ओर बात। आप एक वस्तु के माध्यम से एक स्थैतिक विधि को लागू कर सकते हैं, obj1.staticMethod()
लेकिन वास्तव में इसके लिए चीनी की मात्रा को कम MyClass.staticMethod()
करना चाहिए और इससे बचना चाहिए। यह आमतौर पर आधुनिक आईडीई में एक चेतावनी उठाता है। मुझे नहीं पता कि उन्होंने कभी इस शॉर्टकट की अनुमति क्यों दी।
clazz2 instanceof clazz1
ठीक से उपयोग करने के लिए आप इसके बजाय उपयोग कर सकते हैं class2.isAssignableFrom(clazz1)
, जो मुझे विश्वास है कि आपके उदाहरण में सच होगा।
ओवरराइडिंग को गतिशील प्रेषण द्वारा संभव बनाया गया है , जिसका अर्थ है कि घोषित प्रकार की वस्तु इसके व्यवहार को निर्धारित नहीं करती है, बल्कि इसके अतिरिक्त समय को निर्धारित करती है:
Animal lassie = new Dog();
lassie.speak(); // outputs "woof!"
Animal kermit = new Frog();
kermit.speak(); // outputs "ribbit!"
भले ही दोनों को lassie
और kermit
प्रकार की वस्तुओं के रूप में घोषित किया गया हो Animal
, उनका व्यवहार (विधि .speak()
) भिन्न होता है क्योंकि गतिशील प्रेषण केवल विधि कॉल को चलाने के समय में कार्यान्वित करने के लिए बाध्य करेगा .speak()
- संकलन समय पर नहीं।
अब, यहाँ जहाँ static
कीवर्ड समझ में आने लगता है: "स्थिर" शब्द "डायनामिक" के लिए एक एंटोनॉम है। तो यही कारण है कि आप स्थैतिक विधियों को ओवरराइड नहीं कर सकते हैं क्योंकि स्थैतिक सदस्यों पर कोई गतिशील प्रेषण नहीं है - क्योंकि स्थैतिक का शाब्दिक अर्थ है "गतिशील नहीं"। यदि वे गतिशील रूप से भेजे जाते हैं (और इस तरह से ओवरराइड किया जा सकता है) तो static
कीवर्ड अब समझ में नहीं आएगा।
हाँ। व्यावहारिक रूप से जावा स्थैतिक विधि को ओवरराइड करने की अनुमति देता है, और सैद्धांतिक रूप से यदि आप जावा में एक स्थिर विधि को ओवरराइड करते हैं तो यह संकलित और सुचारू रूप से चलेगा, लेकिन यह पॉलिमॉर्फिज़्म खो देगा जो जावा की मूल संपत्ति है। आप हर जगह पढ़ेंगे कि खुद को संकलित करने और चलाने की कोशिश करना संभव नहीं है। आपको अपना जवाब मिल जाएगा। उदा। यदि आपके पास क्लास एनिमल है और एक स्टैटिक मेथड () खाया जाता है और आप उस सबक्लास में उस स्टैटिक मेथड को ओवरराइड करते हैं तो उसे डॉग कहा जाता है। फिर जब भी आप किसी डॉग ऑब्जेक्ट को एनिमल रेफरेंस के लिए असाइन करते हैं और जावा डॉग के खाने के अनुसार कॉल () खाते हैं, तो उसे कॉल किया जाना चाहिए लेकिन स्टैटिक ओवरराइडिंग एनिमल्स के खाने में () कहा जाएगा।
class Animal {
public static void eat() {
System.out.println("Animal Eating");
}
}
class Dog extends Animal{
public static void eat() {
System.out.println("Dog Eating");
}
}
class Test {
public static void main(String args[]) {
Animal obj= new Dog();//Dog object in animal
obj.eat(); //should call dog's eat but it didn't
}
}
Output Animal Eating
जावा के बहुरूपता सिद्धांत के अनुसार, आउटपुट होना चाहिए Dog Eating
।
लेकिन परिणाम अलग था क्योंकि पॉलिमॉर्फिज्म का समर्थन करने के लिए जावा लेट बाइंडिंग का उपयोग करता है इसका मतलब है कि तरीकों को केवल रन-टाइम पर कहा जाता है लेकिन स्थिर तरीकों के मामले में नहीं। स्थैतिक विधियों में संकलक रन-टाइम के बजाय संकलित समय पर विधियां कहता है, इसलिए हमें संदर्भ के अनुसार विधियाँ मिलती हैं न कि किसी संदर्भ वाली वस्तु के अनुसार, इसीलिए आप कह सकते हैं कि यह व्यावहारिक रूप से स्थैतिक अतिरेक का समर्थन करता है, लेकिन यह नहीं है 'टी।
ओवरराइडिंग पॉलिमॉर्फिक व्यवहार का समर्थन करने के लिए उदाहरण के सदस्यों के लिए आरक्षित है। स्थिर वर्ग के सदस्य किसी विशेष उदाहरण से संबंधित नहीं होते हैं। इसके बजाय, स्थैतिक सदस्य वर्ग के होते हैं और परिणामस्वरूप ओवरराइडिंग का समर्थन नहीं किया जाता है क्योंकि उपवर्ग केवल संरक्षित और सार्वजनिक उदाहरण के सदस्य होते हैं, न कि स्थैतिक सदस्य। आप एक वैकल्पिक दृष्टिकोण का मूल्यांकन करने के लिए एक इनरफेस और रिसर्च फैक्ट्री और / या रणनीति डिजाइन पैटर्न को परिभाषित करना चाह सकते हैं।
जावा (और कई ओओपी भाषाओं में, लेकिन मैं सभी के लिए नहीं बोल सकता हूं; और कुछ में स्थिर नहीं है) सभी विधियों में एक निश्चित हस्ताक्षर हैं - पैरामीटर और प्रकार। एक आभासी विधि में, पहला पैरामीटर निहित है: ऑब्जेक्ट के लिए एक संदर्भ और जब ऑब्जेक्ट के भीतर से कॉल किया जाता है, तो कंपाइलर स्वचालित रूप से जुड़ जाता हैthis
।
स्थैतिक तरीकों के लिए कोई अंतर नहीं है - उनके पास अभी भी एक निश्चित हस्ताक्षर है। हालाँकि, विधि को स्थिर घोषित करके आपने स्पष्ट रूप से कहा है कि संकलक को उस हस्ताक्षर की शुरुआत में निहित ऑब्जेक्ट पैरामीटर शामिल नहीं करना चाहिए। इसलिए, इसे कॉल करने वाले किसी अन्य कोड को स्टैक पर किसी ऑब्जेक्ट के संदर्भ में डालने का प्रयास नहीं करना चाहिए । यदि उसने ऐसा किया, तो विधि निष्पादन काम नहीं करेगा क्योंकि पैरामीटर गलत जगह पर होंगे - एक से स्थानांतरित - स्टैक पर।
इस अंतर के कारण दोनों के बीच; आभासी तरीकों में हमेशा संदर्भ ऑब्जेक्ट (यानी this
) का संदर्भ होता है, इसलिए फिर उस वस्तु के उदाहरण से संबंधित ढेर के भीतर कुछ भी संदर्भित करना संभव है। लेकिन स्थैतिक विधियों के साथ, चूंकि कोई संदर्भ पारित नहीं हुआ है, इसलिए यह विधि किसी भी वस्तु चर और तरीकों का उपयोग नहीं कर सकती है क्योंकि संदर्भ ज्ञात नहीं है।
यदि आप चाहते हैं कि जावा परिभाषा को बदल दे, ताकि हर विधि, स्थैतिक या आभासी के लिए एक वस्तु प्रसंग पारित हो जाए, तो आप सार में केवल आभासी विधियाँ होंगी।
जैसा कि किसी ने op में एक टिप्पणी में पूछा - इस सुविधा को चाहने का आपका कारण और उद्देश्य क्या है?
मैं रूबी को ज्यादा नहीं जानता, जैसा कि ओपी ने बताया था, मैंने कुछ शोध किया। मैं देखता हूं कि रूबी कक्षाएं वास्तव में एक विशेष प्रकार की वस्तु हैं और कोई भी नई विधियां बना सकता है। रूबी में कक्षाएं पूर्ण श्रेणी की वस्तुएं हैं, वे जावा में नहीं हैं। यह सिर्फ कुछ है जिसे आपको जावा (या C #) के साथ काम करते समय स्वीकार करना होगा। ये गतिशील भाषाएं नहीं हैं, हालांकि C # गतिशील के कुछ रूपों को जोड़ रहा है। वास्तव में, रूबी के पास "स्थिर" विधियां नहीं हैं जहां तक मैं पा सकता था - उस स्थिति में ये सिंगलटन क्लास ऑब्जेक्ट पर विधियां हैं। फिर आप एक नए वर्ग के साथ इस सिंगलटन को ओवरराइड कर सकते हैं और पिछली कक्षा की विधियों को नई कक्षा में परिभाषित (सही?) कहेंगे। इसलिए यदि आपने मूल वर्ग के संदर्भ में एक विधि का आह्वान किया है, तो यह अभी भी मूल सांख्यिकीय को निष्पादित करेगा, लेकिन व्युत्पन्न वर्ग में एक विधि को कॉल करना, या तो माता-पिता या उप-वर्ग से तरीकों को कॉल करेगा। दिलचस्प है और मैं इसमें कुछ मूल्य देख सकता हूं। यह एक अलग विचार पैटर्न लेता है।
चूंकि आप जावा में काम कर रहे हैं, इसलिए आपको चीजों को करने के उस तरीके से तालमेल बिठाना होगा। उन्होंने ऐसा क्यों किया? खैर, संभवत: उस समय तकनीक और समझ के आधार पर प्रदर्शन में सुधार करना था जो उपलब्ध था। कंप्यूटर भाषाएँ लगातार विकसित हो रही हैं। काफी दूर तक वापस जाएं और OOP जैसी कोई चीज नहीं है। भविष्य में, अन्य नए विचार होंगे।
संपादित करें : एक अन्य टिप्पणी। अब जब मैं अंतर देख रहा हूं और जैसा कि मैं स्वयं जावा / सी # डेवलपर हूं, तो मैं समझ सकता हूं कि जावा डेवलपर्स से आपको जो उत्तर मिलेंगे, वे भ्रमित करने वाले हो सकते हैं यदि आप रूबी जैसी भाषा से आ रहे हैं। जावा static
विधियां रूबी class
विधियों के समान नहीं हैं । जावा डेवलपर्स को यह समझने में कठिन समय लगेगा, क्योंकि जो लोग रूबी / स्मॉलटॉक जैसी भाषा के साथ काम करते हैं, वे इसके विपरीत होंगे। मैं देख सकता हूं कि यह कैसे इस तथ्य से बहुत भ्रमित होगा कि जावा "क्लास पद्धति" का उपयोग अन्य तरीकों के रूप में स्थैतिक तरीकों के बारे में बात करने के लिए भी करता है, लेकिन इसी शब्द का उपयोग रूबी द्वारा अलग तरीके से किया जाता है। जावा में रूबी स्टाइल क्लास के तरीके नहीं हैं (क्षमा करें); रूबी के पास जावा शैली के स्थिर तरीके नहीं हैं जो वास्तव में सिर्फ पुरानी प्रक्रियात्मक शैली के कार्य हैं, जैसा कि सी में पाया जाता है।
वैसे - सवाल के लिए धन्यवाद! मैंने क्लास के तरीकों (रूबी स्टाइल) के बारे में आज मेरे लिए कुछ नया सीखा।
ठीक है ... जवाब नहीं है, अगर आप इस परिप्रेक्ष्य से सोचते हैं कि जावा में एक ओवरराइड विधि को कैसे व्यवहार किया जाना चाहिए। यदि आप किसी स्थिर विधि को ओवरराइड करने का प्रयास करते हैं, तो आपको कोई कंपाइलर त्रुटि नहीं मिलती है। इसका मतलब है, यदि आप ओवरराइड करने की कोशिश करते हैं, तो जावा आपको ऐसा करने से नहीं रोकता है; लेकिन आप निश्चित रूप से वैसा ही प्रभाव प्राप्त नहीं करते हैं जैसा कि आप गैर-स्थिर तरीकों के लिए करते हैं। जावा में ओवरराइड करने का सीधा मतलब है कि किसी विशेष विधि को ऑब्जेक्ट के रन टाइम प्रकार के आधार पर कहा जाएगा, न कि इसके संकलन समय पर (जो कि स्थैतिक तरीकों के साथ है)। ठीक है ... किसी भी कारण के लिए अनुमान लगाते हैं कि वे अजीब व्यवहार क्यों करते हैं? क्योंकि वे कक्षा के तरीके हैं और इसलिए उनका संकलन हमेशा संकलन समय के दौरान ही संकलित समय प्रकार की जानकारी का उपयोग करके हल किया जाता है।
उदाहरण : आइए देखें कि यदि हम एक स्थैतिक विधि को ओवरराइड करने की कोशिश करते हैं तो क्या होता है: -
class SuperClass {
// ......
public static void staticMethod() {
System.out.println("SuperClass: inside staticMethod");
}
// ......
}
public class SubClass extends SuperClass {
// ......
// overriding the static method
public static void staticMethod() {
System.out.println("SubClass: inside staticMethod");
}
// ......
public static void main(String[] args) {
// ......
SuperClass superClassWithSuperCons = new SuperClass();
SuperClass superClassWithSubCons = new SubClass();
SubClass subClassWithSubCons = new SubClass();
superClassWithSuperCons.staticMethod();
superClassWithSubCons.staticMethod();
subClassWithSubCons.staticMethod();
// ...
}
}
आउटपुट : -
SuperClass: inside staticMethod
SuperClass: inside staticMethod
SubClass: inside staticMethod
आउटपुट की दूसरी लाइन पर ध्यान दें। जब स्टेटमैथोड को ओवरराइड किया गया था तो यह लाइन तीसरी लाइन के समान होनी चाहिए थी क्योंकि हम रनटाइम टाइप के ऑब्जेक्ट पर 'स्टेटमैथोड ()' को 'सबक्लास्स' के रूप में लिख रहे हैं और 'सुपरक्लास' के रूप में नहीं। यह पुष्टि करता है कि स्थिर तरीकों को हमेशा उनके संकलन समय प्रकार की जानकारी का उपयोग करके हल किया जाता है।
सामान्य तौर पर यह स्थिर तरीकों की 'ओवरराइडिंग' की अनुमति देने के लिए कोई मतलब नहीं है क्योंकि यह निर्धारित करने का कोई अच्छा तरीका नहीं होगा कि कौन से रनटाइम पर कॉल किया जाए। कर्मचारी का उदाहरण लेते हुए, अगर हम RegularEmployee.getBonusMultiplier () कहते हैं - किस विधि को निष्पादित किया जाना है?
जावा के मामले में, कोई भी भाषा की परिभाषा की कल्पना कर सकता है जहां किसी वस्तु के उदाहरण के माध्यम से उन्हें तब तक स्थिर तरीकों से 'ओवरराइड' करना संभव है। हालाँकि, यह सब करना होगा नियमित कक्षा विधियों को फिर से लागू करना, बिना किसी लाभ के वास्तव में भाषा के साथ अतिरेक जोड़ना।
ओवरराइड करके हम ऑब्जेक्ट प्रकार के आधार पर बहुरूपी प्रकृति बना सकते हैं। स्थैतिक विधि का वस्तु से कोई संबंध नहीं है। इसलिए जावा स्थैतिक विधि का समर्थन नहीं कर सकता।
मुझे जे और की टिप्पणी पसंद है ( https://stackoverflow.com/a/2223803/1517187 )।
मैं मानता हूं कि यह जावा का खराब डिजाइन है।
कई अन्य भाषाएँ स्थैतिक तरीकों को ओवरराइड करने का समर्थन करती हैं, जैसा कि हम पिछली टिप्पणियों में देखते हैं। मुझे लगता है कि जेई भी मेरी तरह डेल्फी से जावा आए हैं।
डेल्फी (ऑब्जेक्ट पास्कल) ओओपी को लागू करने वाली पहली भाषा थी।
यह स्पष्ट है कि कई लोगों के पास उस भाषा के साथ अनुभव था क्योंकि यह वाणिज्यिक जीयूआई उत्पादों को लिखने के लिए एकमात्र भाषा थी। और - हाँ, हम डेल्फी में स्थैतिक तरीकों को ओवरराइड कर सकते हैं। दरअसल, डेल्फी में स्थिर तरीकों को "क्लास मेथड्स" कहा जाता है, जबकि डेल्फी में "डेल्फी स्टैटिक मेथड्स" की अलग अवधारणा थी, जो शुरुआती बाइंडिंग के तरीके थे। देर से बाध्यकारी का उपयोग करने के तरीकों को ओवरराइड करने के लिए, "आभासी" निर्देश की घोषणा करें। इसलिए यह बहुत सुविधाजनक और सहज था और मैं जावा में इसकी उम्मीद करूंगा।
स्थैतिक तरीकों को ओवरराइड करने के लिए यह क्या अच्छा करेगा। आप एक उदाहरण के माध्यम से स्थिर तरीकों को नहीं कह सकते।
MyClass.static1()
MySubClass.static1() // If you overrode, you have to call it through MySubClass anyway.
संपादित करें: ऐसा प्रतीत होता है कि भाषा डिजाइन में एक दुर्भाग्यपूर्ण निरीक्षण के माध्यम से, आप एक उदाहरण के माध्यम से स्थैतिक तरीकों को कॉल कर सकते हैं । आम तौर पर कोई भी ऐसा नहीं करता है। मेरी गलती।
variable.staticMethod()
, इसके बजाय Class.staticMethod()
, variable
घोषित प्रकार के साथ एक चर कहां है Class
। मैं मानता हूं कि यह खराब भाषा डिजाइन है।
जावा में ओवरराइड करने का सीधा मतलब है कि किसी विशेष विधि को ऑब्जेक्ट के रनटाइम प्रकार के आधार पर कहा जाएगा न कि इसके संकलन-समय प्रकार पर (जो ओवरराइड स्टैटिक विधियों के साथ मामला है)। चूंकि स्टैटिक मेथड्स क्लास मेथड हैं, वे इंस्टेंस मेथड नहीं हैं, इसलिए उनका इस तथ्य से कोई लेना-देना नहीं है कि संदर्भ किस ऑब्जेक्ट या इंस्टेंस की ओर इशारा करता है, क्योंकि स्टैटिक विधि की प्रकृति के कारण यह एक विशिष्ट वर्ग से संबंधित है। आप इसे उपवर्ग में पुन: प्रकाशित कर सकते हैं लेकिन उस उपवर्ग को अभिभावक वर्ग के स्थैतिक तरीकों के बारे में कुछ भी पता नहीं चलेगा, क्योंकि जैसा कि मैंने कहा, यह केवल उस वर्ग के लिए विशिष्ट है जिसमें यह घोषित किया गया है। ऑब्जेक्ट संदर्भों का उपयोग करके उन्हें एक्सेस करना जावा के डिजाइनरों द्वारा दी गई एक अतिरिक्त स्वतंत्रता है और हमें निश्चित रूप से उस अभ्यास को रोकने के बारे में नहीं सोचना चाहिए, जब वे इसे अधिक विवरण और उदाहरण के लिए प्रतिबंधित करते हैं। http://faisalbhagat.blogspot.com/2014/09/method-overriding-and-method-hiding.html
ओवरराइड करके, आप गतिशील बहुरूपता प्राप्त करते हैं। जब आप स्थैतिक तरीकों को ओवरराइड करते हुए कहते हैं, तो आप जिन शब्दों का उपयोग करने की कोशिश कर रहे हैं, वे विरोधाभासी हैं।
स्टेटिक कहता है - संकलन का समय, ओवरराइडिंग का उपयोग गतिशील बहुरूपता के लिए किया जाता है। दोनों प्रकृति में विपरीत हैं, और इसलिए एक साथ उपयोग नहीं किया जा सकता है।
डायनेमिक बहुरूपता व्यवहार तब आता है जब एक प्रोग्रामर एक ऑब्जेक्ट का उपयोग करता है और एक इंस्टेंस विधि का उपयोग करता है। जेआरई विभिन्न वर्गों के विभिन्न उदाहरणों को मैप करेगा जो इस आधार पर होगा कि आप किस तरह की वस्तु का उपयोग कर रहे हैं।
जब आप स्थैतिक विधियों को ओवरराइड करते हुए कहते हैं, स्थैतिक विधियाँ हम वर्ग नाम का उपयोग करके प्राप्त करेंगे, जिसे संकलन समय पर लिंक किया जाएगा, इसलिए स्थैतिक विधियों के साथ रनटाइम पर विधियों को जोड़ने की कोई अवधारणा नहीं है। अतः "स्टैटिक मेथड्स" शब्द का कोई मतलब नहीं है।
नोट: भले ही आप किसी ऑब्जेक्ट के साथ क्लास विधि का उपयोग करते हैं, फिर भी जावा कंपाइलर इसे खोजने के लिए पर्याप्त बुद्धिमान है, और स्थैतिक लिंकिंग करेगा।
Box.createBox
तुलना में अधिक समझ में आता है BoxFactory.createBox
, और एक अपरिहार्य पैटर्न है जब अपवाद फेंकने के बिना निर्माण की त्रुटि की जांच करने की आवश्यकता होती है (निर्माता विफल नहीं हो सकते, वे केवल प्रक्रिया को मार सकते हैं / फेंक सकते हैं अपवाद), जबकि एक स्थिर विधि विफलता पर अशक्त हो सकती है, या यहां तक कि सफलता / त्रुटि कॉलबैक को स्वीकार कर सकती है जैसे hastebin.com/codajahati.java ।
इस प्रश्न का उत्तर सरल है, स्थैतिक के रूप में चिह्नित विधि या चर केवल वर्ग के अंतर्गत आता है, ताकि स्थैतिक विधि को उप वर्ग में विरासत में प्राप्त नहीं किया जा सके क्योंकि वे केवल सुपर वर्ग से संबंधित हैं।
आसान समाधान: सिंगलटन उदाहरण का उपयोग करें। यह ओवरराइड और वंशानुक्रम की अनुमति देगा।
मेरे सिस्टम में, मेरे पास सिंगलेट्स रेजिस्ट्री क्लास है, जो उत्तीर्ण वर्ग के लिए उदाहरण देता है। यदि उदाहरण नहीं मिलता है, तो यह बनाया जाता है।
Haxe भाषा वर्ग:
package rflib.common.utils;
import haxe.ds.ObjectMap;
class SingletonsRegistry
{
public static var instances:Map<Class<Dynamic>, Dynamic>;
static function __init__()
{
StaticsInitializer.addCallback(SingletonsRegistry, function()
{
instances = null;
});
}
public static function getInstance(cls:Class<Dynamic>, ?args:Array<Dynamic>)
{
if (instances == null) {
instances = untyped new ObjectMap<Dynamic, Dynamic>();
}
if (!instances.exists(cls))
{
if (args == null) args = [];
instances.set(cls, Type.createInstance(cls, args));
}
return instances.get(cls);
}
public static function validate(inst:Dynamic, cls:Class<Dynamic>)
{
if (instances == null) return;
var inst2 = instances[cls];
if (inst2 != null && inst != inst2) throw "Can\'t create multiple instances of " + Type.getClassName(cls) + " - it's singleton!";
}
}
Singleton.get()
। रजिस्ट्री बस बॉयलरप्लेट ओवरहेड है, और यह जीसी को कक्षाओं में शामिल करती है।
एक स्थिर विधि, परिवर्तनशील, ब्लॉक या नेस्टेड वर्ग पूरे वर्ग के अंतर्गत आता है एक वस्तु के बजाय से संबंधित है।
जावा में एक विधि का उपयोग ऑब्जेक्ट / क्लास के व्यवहार को उजागर करने के लिए किया जाता है। यहां, चूंकि विधि स्थिर है (अर्थात, केवल किसी वर्ग के व्यवहार को दर्शाने के लिए स्थिर विधि का उपयोग किया जाता है।) संपूर्ण कक्षा के व्यवहार को बदलने / ओवरराइड करने से ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग के मूलभूत स्तंभों में से एक, यानी उच्च सामंजस्य की घटना का उल्लंघन होगा। । (याद रखें एक निर्माता जावा में एक विशेष प्रकार की विधि है।)
उच्च सामंजस्य - एक वर्ग की केवल एक भूमिका होनी चाहिए। उदाहरण के लिए: एक कार वर्ग को केवल कार ऑब्जेक्ट का उत्पादन करना चाहिए न कि बाइक, ट्रक, प्लेन इत्यादि। लेकिन कार क्लास में कुछ विशेषताएं (व्यवहार) हो सकती हैं जो स्वयं के लिए हैं।
इसलिए, जावा प्रोग्रामिंग भाषा डिजाइन करते समय। भाषा डिजाइनरों ने सोचा कि डेवलपर्स केवल प्रकृति में एक विधि को स्थिर बनाकर केवल एक वर्ग के कुछ व्यवहारों को रखने की अनुमति देते हैं।
नीचे का टुकड़ा कोड स्थिर विधि को ओवरराइड करने की कोशिश करता है, लेकिन किसी भी संकलन की त्रुटि का सामना नहीं करेगा ।
public class Vehicle {
static int VIN;
public static int getVehileNumber() {
return VIN;
}}
class Car extends Vehicle {
static int carNumber;
public static int getVehileNumber() {
return carNumber;
}}
ऐसा इसलिए है, क्योंकि यहां हम एक विधि को ओवरराइड नहीं कर रहे हैं, लेकिन हम इसे फिर से घोषित कर रहे हैं। जावा एक विधि (स्थिर / गैर-स्थैतिक) की पुनः घोषणा की अनुमति देता है।
कार श्रेणी के getVehileNumber () विधि से स्थिर कीवर्ड को हटाने से संकलन त्रुटि हो जाएगी, क्योंकि, हम स्थैतिक विधि की कार्यक्षमता को बदलने की कोशिश कर रहे हैं जो केवल वाहन वर्ग से संबंधित है।
इसके अलावा, अगर getVehileNumber () को अंतिम घोषित किया जाता है, तो कोड संकलित नहीं होगा, क्योंकि अंतिम कीवर्ड प्रोग्रामर को फिर से विधि घोषित करने से रोकता है।
public static final int getVehileNumber() {
return VIN; }
कुल मिलाकर, यह सॉफ्टवेयर डिजाइनर है जहां स्थैतिक विधियों का उपयोग करना है। मैं व्यक्तिगत रूप से किसी भी वर्ग का उदाहरण बनाए बिना कुछ कार्यों को करने के लिए स्थैतिक तरीकों का उपयोग करना पसंद करता हूं। दूसरे, बाहरी दुनिया से एक वर्ग के व्यवहार को छिपाने के लिए।
यहाँ एक सरल व्याख्या है। एक स्थिर विधि एक वर्ग से जुड़ी होती है जबकि एक आवृत्ति विधि किसी विशेष वस्तु से जुड़ी होती है। ओवरराइड्स विशेष वस्तु से जुड़े ओवरराइड तरीकों के विभिन्न कार्यान्वयन को कॉल करने की अनुमति देते हैं। तो यह स्थैतिक विधि को ओवरराइड करने के लिए काउंटर-सहज है जो वस्तुओं से जुड़ा नहीं है, लेकिन पहली जगह में ही वर्ग है। इसलिए स्थैतिक तरीकों को इस बात के आधार पर अधिभूत नहीं किया जा सकता है कि कौन सी वस्तु इसे बुला रही है, यह हमेशा उस वर्ग से जुड़ा होगा जहां इसे बनाया गया था।
public abstract IBox createBox();
अंदर IBox इंटरफ़ेस के लिए सहज ज्ञान युक्त है ? बॉक्स बायबॉक्स को ओवरराइड करने के लिए IBox को लागू कर सकता है, और एक वैध IBox में ऑब्जेक्ट परिणाम का निर्माण होता है, अन्यथा एक अशक्त वापस आ जाता है। कंस्ट्रक्टर "null" वापस नहीं कर सकते हैं और इसलिए आपको (1) अपवादों का उपयोग करने के लिए मजबूर किया जाता है (हम अभी क्या करते हैं), या (2) कारखाने की कक्षाएं बनाते हैं जो मैंने पहले कहा था, लेकिन एक तरह से जो novices या विशेषज्ञों का कोई मतलब नहीं है जावा का (जो अब हम भी करते हैं)। स्टेटिक अनइम्प्लीमेंटेड मेथड्स इसे हल करते हैं।
अब उपर्युक्त उत्तरों को देखकर सभी को पता है कि हम स्थैतिक तरीकों से आगे नहीं बढ़ सकते हैं, लेकिन किसी को उपवर्ग से स्थिर तरीकों तक पहुँचने की अवधारणा के बारे में गलतफहमी नहीं होनी चाहिए ।
हम सुपर क्लास के स्टैटिक तरीकों को उपवर्ग संदर्भ के साथ एक्सेस कर सकते हैं यदि यह स्टैटिक तरीका सब क्लास में परिभाषित नए स्टैटिक मेथड द्वारा छिपाया नहीं गया है।
उदाहरण के लिए, नीचे दिया गया कोड देखें: -
public class StaticMethodsHiding {
public static void main(String[] args) {
SubClass.hello();
}
}
class SuperClass {
static void hello(){
System.out.println("SuperClass saying Hello");
}
}
class SubClass extends SuperClass {
// static void hello() {
// System.out.println("SubClass Hello");
// }
}
आउटपुट: -
SuperClass saying Hello
उप-वर्ग में स्थैतिक तरीकों को छिपाने के बारे में जानकारी के लिए जावा ऑरेकल डॉक्स देखें और आप जो कर सकते हैं उसे एक उपवर्ग में खोजें।
धन्यवाद
निम्न कोड दिखाता है कि यह संभव है:
class OverridenStaticMeth {
static void printValue() {
System.out.println("Overriden Meth");
}
}
public class OverrideStaticMeth extends OverridenStaticMeth {
static void printValue() {
System.out.println("Overriding Meth");
}
public static void main(String[] args) {
OverridenStaticMeth osm = new OverrideStaticMeth();
osm.printValue();
System.out.println("now, from main");
printValue();
}
}
osm
है OverridenStaticMeth
नहीं OverrideStaticMeth
।