सवाल जावा में है कि मैं एक अमूर्त स्टेटिक विधि को परिभाषित क्यों नहीं कर सकता? उदाहरण के लिए
abstract class foo {
abstract void bar( ); // <-- this is ok
abstract static void bar2(); //<-- this isn't why?
}
सवाल जावा में है कि मैं एक अमूर्त स्टेटिक विधि को परिभाषित क्यों नहीं कर सकता? उदाहरण के लिए
abstract class foo {
abstract void bar( ); // <-- this is ok
abstract static void bar2(); //<-- this isn't why?
}
जवाबों:
क्योंकि "अमूर्त" का अर्थ होता है: "इम्प्लीमेंट्स नो फंक्शनलिटी", और "स्टैटिस्टिकल" का अर्थ है: "यदि आपके पास वस्तु उदाहरण नहीं है तो भी कार्यक्षमता है"। और यह एक तार्किक विरोधाभास है।
abstract staticहोती तो सही अर्थ होता। यह स्वयं क्लास ऑब्जेक्ट का एक तरीका होगा जो सबक्लास ऑब्जेक्ट्स को लागू करना होगा। बेशक, भाषा के बारे में मेरी पकड़ के बावजूद चीजें जिस तरह से आपका जवाब देती हैं, वह सही है।
abstract static: एक फ़ंक्शन एक्स जो "उपवर्ग में लागू किया गया है" एक ही समय में "कक्षा पर निष्पादित" नहीं हो सकता है - केवल उपवर्ग पर । जहां यह तब अमूर्त नहीं है।
static"खाली नहीं" का मतलब यह नहीं है - यह जावा के सिर्फ एक परिणाम है जो स्थिर तरीकों को अमूर्त नहीं होने देता है। इसका मतलब है "क्लास पर कॉल करने योग्य।" (इसका मतलब " क्लास पर केवल कॉल करने योग्य " होना चाहिए, लेकिन यह एक और मुद्दा है।) यदि जावा समर्थित abstract staticविधियां हैं, तो मुझे यह उम्मीद होगी कि विधि 1) उपवर्गों द्वारा लागू की जानी चाहिए, और 2) उपवर्ग का एक वर्ग तरीका है। कुछ तरीके सिर्फ उदाहरण के तरीकों के रूप में समझ में नहीं आते हैं। दुर्भाग्य से जावा आपको निर्दिष्ट नहीं करता है कि अमूर्त आधार वर्ग (या इंटरफ़ेस) बनाते समय।
खराब भाषा डिजाइन। यह केवल उस अमूर्त विधि का उपयोग करने के लिए एक उदाहरण बनाने की तुलना में सीधे एक स्थिर अमूर्त विधि को कॉल करने के लिए अधिक प्रभावी होगा। विशेष रूप से सच है जब विस्तार करने में असमर्थता के लिए एक सार के रूप में एक सार वर्ग का उपयोग किया जाता है, जो एक और खराब डिजाइन उदाहरण है। आशा है कि वे अगली रिलीज में उन सीमाओं को हल करेंगे।
staticस्वयं की अवधारणा पहले से ही एक उल्लंघन है ....
आप एक स्थैतिक विधि को ओवरराइड नहीं कर सकते, इसलिए इसे अमूर्त बनाना अर्थहीन होगा। इसके अलावा, एक अमूर्त वर्ग में एक स्थिर विधि उस वर्ग की होती है, और ओवरराइडिंग क्लास नहीं, इसलिए उसका उपयोग नहीं किया जा सकता है।
abstractएक पद्धति के लिए एनोटेशन इंगित करता है कि विधि एक उपवर्ग में ओवरराइड किया जाना चाहिए।
जावा में, एक staticसदस्य (विधि या क्षेत्र) को उपवर्गों द्वारा ओवरराइड नहीं किया जा सकता है (यह जरूरी नहीं कि अन्य ऑब्जेक्ट ओरिएंटेड भाषाओं में सही हो, स्मॉलटॉक देखें।) एक staticसदस्य छिपा हो सकता है , लेकिन यह ओवरराइड की तुलना में मौलिक रूप से भिन्न है ।
चूंकि एक उपवर्ग में स्थिर सदस्यों को ओवरराइड नहीं किया जा सकता है, इसलिए abstractएनोटेशन उन पर लागू नहीं किया जा सकता है।
एक तरफ के रूप में - अन्य भाषाएँ स्थैतिक विरासत का समर्थन करती हैं, उदाहरण की विरासत की तरह। एक वाक्यविन्यास परिप्रेक्ष्य से, उन भाषाओं को आमतौर पर कथन में वर्ग नाम शामिल करने की आवश्यकता होती है। उदाहरण के लिए, जावा में, यह मानते हुए कि आप ClassA में कोड लिख रहे हैं, ये समतुल्य कथन हैं (यदि मेथड () एक स्थिर विधि है, और एक ही हस्ताक्षर के साथ कोई इंस्टेंस विधि नहीं है):
ClassA.methodA();
तथा
methodA();
SmallTalk में, वर्ग नाम वैकल्पिक नहीं है, इसलिए वाक्यविन्यास है (ध्यान दें कि SmallTalk "विषय" और "क्रिया" को अलग करने के लिए उपयोग नहीं करता है, बल्कि इसके बजाय स्टेटमेड टर्मिनेटर के रूप में उपयोग करता है):
ClassA methodA.
क्योंकि वर्ग नाम हमेशा आवश्यक होता है, विधि का सही "संस्करण" हमेशा वर्ग पदानुक्रम को निर्धारित करके निर्धारित किया जा सकता है। इसके लायक होने के लिए, मैं कभी-कभार staticविरासत को याद करता हूं, और जब मैंने पहली बार इसके साथ शुरुआत की थी, तो जावा में स्थिर विरासत की कमी से काट लिया गया था। इसके अतिरिक्त, SmallTalk डक-टंकित है (और इस प्रकार प्रोग्राम-बाय-कॉन्ट्रैक्ट का समर्थन नहीं करता है।) इस प्रकार, इसमें abstractक्लास के सदस्यों के लिए कोई संशोधक नहीं है ।
मैंने भी यही सवाल पूछा, यहाँ क्यों है
चूंकि सार वर्ग कहता है, यह कार्यान्वयन नहीं देगा और उपवर्ग को इसे देने की अनुमति देगा
इसलिए सबक्लास को सुपरक्लास के तरीकों को ओवरराइड करना पड़ा,
नियम नंबर 1 - एक स्थिर विधि को ओवरराइड नहीं किया जा सकता है
क्योंकि स्थैतिक सदस्य और विधियाँ समय के तत्व संकलित होते हैं, इसीलिए स्थैतिक विधियों के अतिभार (संकलित समय बहुरूपता) की अनुमति दी जाती है, बजाय इसके बाद (रंटाइम पोलिमोर्फिज्म)
इसलिए, वे सार नहीं हो सकते।
अमूर्त स्थिर जैसी कोई चीज नहीं है <--- जावा यूनिवर्स में अनुमति नहीं है
abstract staticदेखने stackoverflow.com/questions/370962/... । जावा के स्थैतिक तरीकों की अनुमति नहीं देने का असली कारण यह है कि जावा स्थैतिक तरीकों को ओवरराइड नहीं होने देता है।
foo(String)ही नहीं है foo(Integer)- यह सब है।
यह एक भयानक भाषा डिजाइन है और वास्तव में इसका कोई कारण नहीं है कि यह कैसे संभव हो सकता है।
वास्तव में, यहाँ कैसे इस पर एक कार्यान्वयन है सकते में किया जा जावा :
public class Main {
public static void main(String[] args) {
// This is done once in your application, usually at startup
Request.setRequest(new RequestImplementationOther());
Request.doSomething();
}
public static final class RequestImplementationDefault extends Request {
@Override
void doSomethingImpl() {
System.out.println("I am doing something AAAAAA");
}
}
public static final class RequestImplementaionOther extends Request {
@Override
void doSomethingImpl() {
System.out.println("I am doing something BBBBBB");
}
}
// Static methods in here can be overriden
public static abstract class Request {
abstract void doSomethingImpl();
// Static method
public static void doSomething() {
getRequest().doSomethingImpl();
}
private static Request request;
private static Request getRequest() {
// If setRequest is never called prior, it will default to a default implementation. Of course you could ignore that too.
if ( request == null ) {
return request = new RequestImplementationDefault();
}
return request;
}
public static Request setRequest(Request r){
return request = r;
}
}
}
================= पुरानी मिसाल नीचे ================= नीचे
GetRequest, और getRequestImpl के लिए देखें ... setInstance को कॉल करने से पहले कार्यान्वयन को बदलने के लिए कहा जा सकता है।
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* @author Mo. Joseph
* @date 16 mar 2012
**/
public abstract class Core {
// ---------------------------------------------------------------
private static Core singleton;
private static Core getInstance() {
if ( singleton == null )
setInstance( new Core.CoreDefaultImpl() ); // See bottom for CoreDefaultImpl
return singleton;
}
public static void setInstance(Core core) {
Core.singleton = core;
}
// ---------------------------------------------------------------
// Static public method
public static HttpServletRequest getRequest() {
return getInstance().getRequestImpl();
}
// A new implementation would override this one and call setInstance above with that implementation instance
protected abstract HttpServletRequest getRequestImpl();
// ============================ CLASSES =================================
// ======================================================================
// == Two example implementations, to alter getRequest() call behaviour
// == getInstance() have to be called in all static methods for this to work
// == static method getRequest is altered through implementation of getRequestImpl
// ======================================================================
/** Static inner class CoreDefaultImpl */
public static class CoreDefaultImpl extends Core {
protected HttpServletRequest getRequestImpl() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
}
/** Static inner class CoreTestImpl : Alternative implementation */
public static class CoreTestImpl extends Core {
protected HttpServletRequest getRequestImpl() {
return new MockedRequest();
}
}
}
अनुसरण के रूप में उपयोग किया जाता है:
static {
Core.setSingleton(new Core.CoreDefaultImpl());
// Or
Core.setSingleton(new Core.CoreTestImpl());
// Later in the application you might use
Core.getRequest();
}
abstract staticप्रश्न में पूछे गए तरीके का उदाहरण कहां दिया है और आपने बोल्ड कैन बी डन इन जावा में लिखा है । यह पूरी तरह से भ्रामक है।
एक अमूर्त विधि को केवल इसलिए परिभाषित किया जाता है ताकि इसे उपवर्ग में ओवरराइड किया जा सके। हालांकि, स्थिर तरीकों को ओवरराइड नहीं किया जा सकता है। इसलिए, अमूर्त, स्थिर विधि के लिए यह एक संकलन-समय की त्रुटि है।
अब अगला सवाल यह है कि स्थैतिक तरीकों को ओवरराइड क्यों नहीं किया जा सकता है ??
यह इसलिए है क्योंकि स्थैतिक विधियाँ किसी विशेष वर्ग की होती हैं न कि उसके उदाहरण की। यदि आप किसी स्थिर विधि को ओवरराइड करने का प्रयास करते हैं, तो आपको कोई संकलन या रनटाइम त्रुटि नहीं मिलेगी, लेकिन कंपाइलर सुपरक्लास की स्थिर विधि को छिपा देगा।
एक स्थिर विधि, परिभाषा के अनुसार, जानने की जरूरत नहीं है this। इस प्रकार, यह एक आभासी तरीका नहीं हो सकता है (जो कि गतिशील उप-वर्ग जानकारी के अनुसार अतिभारित है this); इसके बजाय, एक स्थिर विधि अधिभार केवल संकलन समय पर उपलब्ध जानकारी के आधार पर है (इसका मतलब है: एक बार जब आप सुपरक्लास की एक स्थिर विधि का उल्लेख करते हैं, तो आप इसे सुपरक्लास विधि कहते हैं, लेकिन कभी भी उप-वर्ग विधि नहीं)।
इसके अनुसार, अमूर्त स्थैतिक विधियां काफी बेकार होंगी क्योंकि आप कभी भी इसका संदर्भ कुछ परिभाषित निकाय द्वारा प्रतिस्थापित नहीं करेंगे।
मैं देखता हूं कि पहले से ही एक ईश्वर-ज़िलिन उत्तर हैं लेकिन मुझे कोई व्यावहारिक समाधान नहीं दिखता है। बेशक यह एक वास्तविक समस्या है और जावा में इस सिंटैक्स को बाहर करने का कोई अच्छा कारण नहीं है। चूंकि मूल प्रश्न में एक संदर्भ का अभाव है, जहाँ इसकी आवश्यकता हो सकती है, मैं एक संदर्भ और एक समाधान प्रदान करता हूं:
मान लीजिए कि आपके पास कक्षाओं का एक समूह है जो समान हैं। ये विधियाँ एक विशिष्ट विधि कहलाती हैं जो विशिष्ट है:
class C1 {
static void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
private static void doMoreWork(int k) {
// code specific to class C1
}
}
class C2 {
static void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
private static void doMoreWork(int k) {
// code specific to class C2
}
}
doWork()तरीकों C1और C2समान हैं। इनमें से बहुत सी खामियां हो सकती हैं: C3 C4आदि। यदि static abstractअनुमति दी गई थी, तो आप कुछ ऐसा करके डुप्लिकेट कोड को समाप्त कर देंगे:
abstract class C {
static void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
static abstract void doMoreWork(int k);
}
class C1 extends C {
private static void doMoreWork(int k) {
// code for class C1
}
}
class C2 extends C {
private static void doMoreWork(int k) {
// code for class C2
}
}
लेकिन यह संकलित नहीं होगा क्योंकि static abstractसंयोजन की अनुमति नहीं है। हालाँकि, इसे static classनिर्माण के साथ दरकिनार किया जा सकता है , जिसकी अनुमति है:
abstract class C {
void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
abstract void doMoreWork(int k);
}
class C1 {
private static final C c = new C(){
@Override void doMoreWork(int k) {
System.out.println("code for C1");
}
};
public static void doWork() {
c.doWork();
}
}
class C2 {
private static final C c = new C() {
@Override void doMoreWork(int k) {
System.out.println("code for C2");
}
};
public static void doWork() {
c.doWork();
}
}
इस समाधान के साथ केवल एक ही कोड डुप्लिकेट है
public static void doWork() {
c.doWork();
}
C1.doWork()या C2.doWork()लेकिन आप कॉल नहीं कर सकते C.doWork()। इसके अलावा, आपके द्वारा प्रदान किए गए उदाहरण में, जो काम नहीं करेगा, मान लीजिए कि अगर इसकी अनुमति दी गई है, तो क्लास किस तरह Cसे कार्यान्वयन का पता लगाएगा doMoreWork()? अंत में मैं आपके संदर्भ कोड को एक खराब डिज़ाइन कहूंगा। क्यों? केवल इसलिए कि आपने कोड के लिए एक अलग फ़ंक्शन बनाया है जो उस कोड के लिए फ़ंक्शन बनाने के बजाय जो सामान्य है और फिर कक्षा में एक स्थिर फ़ंक्शन को लागू कर रहा है C। यह आसान है !!!
मान लें कि दो वर्ग हैं, Parentऔर Child। Parentहै abstract। घोषणाएं इस प्रकार हैं:
abstract class Parent {
abstract void run();
}
class Child extends Parent {
void run() {}
}
इसका मतलब यह है कि किसी भी उदाहरण Parentको निर्दिष्ट करना चाहिए कि कैसे run()निष्पादित किया जाता है।
हालाँकि, अब मान लें कि Parentयह नहीं है abstract।
class Parent {
static void run() {}
}
इसका मतलब है कि Parent.run()स्थैतिक विधि को निष्पादित करेगा।
एक abstractविधि की परिभाषा "एक विधि है जिसे घोषित किया गया है लेकिन लागू नहीं किया गया है", जिसका अर्थ है कि यह स्वयं कुछ भी वापस नहीं करता है।
एक staticविधि की परिभाषा "एक विधि है जो समान मापदंडों के लिए उसी मान को लौटाती है, जिस पर इसे कहा जाता है"।
abstractउदाहरण बदलते ही एक विधि का रिटर्न वैल्यू बदल जाएगा। एक staticतरीका नहीं होगा। एक static abstractविधि बहुत अधिक एक विधि है जहां वापसी मूल्य स्थिर है, लेकिन कुछ भी वापस नहीं करता है। यह एक तार्किक विरोधाभास है।
इसके अलावा, एक static abstractविधि के लिए वास्तव में बहुत अधिक कारण नहीं है ।
एक सार वर्ग में एक स्थिर विधि नहीं हो सकती है क्योंकि डायनामिक बाइंडिंग को प्राप्त करने के लिए एब्स्ट्रेक्शन किया जाता है जबकि स्थिर विधियों को सांख्यिकीय रूप से उनकी कार्यक्षमता के लिए बाध्य किया जाता है। स्टैटिक विधि का मतलब है कि व्यवहार एक चर चर पर निर्भर नहीं है, इसलिए कोई उदाहरण / वस्तु की आवश्यकता नहीं है। कक्षा का निरीक्षण करें। स्थैतिक विधियाँ वर्ग की होती हैं न कि वस्तु की। उन्हें एक मेमोरी क्षेत्र में संग्रहीत किया जाता है जिसे PERMGEN के रूप में जाना जाता है जहां से इसे हर वस्तु के साथ साझा किया जाता है। अमूर्त वर्ग के तरीके गतिशील रूप से उनकी कार्यक्षमता के लिए बाध्य होते हैं।
एक विधि के रूप की घोषणा staticका मतलब है हम अपने वर्ग के नाम से उस विधि कॉल कर सकते हैं और यदि उस वर्ग है abstractऔर साथ ही, यह कोई मतलब नहीं है इसे कहते हैं के रूप में यह शरीर के किसी भी शामिल नहीं है, और इसलिए हम दोनों के रूप में एक प्रणाली की घोषणा नहीं कर सकते हैं staticऔर abstract।
जैसा कि अमूर्त विधियाँ वर्ग से संबंधित हैं और क्रियान्वयन वर्ग द्वारा इसे ओवरराइड नहीं किया जा सकता है। यदि एक ही हस्ताक्षर के साथ एक स्थिर विधि है, तो यह विधि को छुपाता है, इसे ओवरराइड नहीं करता है। तो यह अमूर्त विधि को स्थिर घोषित करने के लिए स्थिर है क्योंकि यह शरीर को कभी नहीं मिलेगा। यह, समय त्रुटि को संकलित करें।
एक स्थिर विधि को कक्षा के उदाहरण के बिना कहा जा सकता है। अपने उदाहरण में आप foo.bar2 () कह सकते हैं, लेकिन foo.bar () नहीं, क्योंकि बार के लिए आपको एक उदाहरण की आवश्यकता होती है। निम्नलिखित कोड काम करेगा:
foo var = new ImplementsFoo();
var.bar();
यदि आप एक स्थिर विधि कहते हैं, तो इसे हमेशा एक ही कोड निष्पादित किया जाएगा। उपरोक्त उदाहरण में, भले ही आप ImplementsFoo में बार 2 को फिर से परिभाषित करें, var.bar2 () पर कॉल foo.bar2 () निष्पादित करेगा।
यदि बार 2 में अब कोई कार्यान्वयन नहीं है (जो कि सार का मतलब है), तो आप कार्यान्वयन के बिना एक विधि कह सकते हैं। यह बहुत हानिकारक है।
मेरा मानना है कि मुझे इस सवाल का जवाब मिल गया है, क्यों एक इंटरफ़ेस के तरीके (जो एक मूल वर्ग में अमूर्त तरीकों की तरह काम करते हैं) स्थिर नहीं हो सकते। यहाँ पूरा जवाब है (मेरा नहीं)
मूल रूप से स्थिर तरीकों का संकलन समय पर किया जा सकता है, क्योंकि उन्हें कॉल करने के लिए आपको एक वर्ग निर्दिष्ट करने की आवश्यकता होती है। यह उदाहरण के तरीकों से अलग है, जिसके लिए जिस संदर्भ से आप विधि को कॉल कर रहे हैं उसका वर्ग संकलन समय पर अज्ञात हो सकता है (इस प्रकार जिसे कोड ब्लॉक कहा जाता है वह केवल रनटाइम पर निर्धारित किया जा सकता है)।
यदि आप एक स्थिर पद्धति को कॉल कर रहे हैं, तो आप पहले से ही उस वर्ग को जानते हैं जहां यह लागू किया गया है, या इसका कोई प्रत्यक्ष उपवर्ग। यदि आप परिभाषित करते हैं
abstract class Foo {
abstract static void bar();
}
class Foo2 {
@Override
static void bar() {}
}
फिर कोई भी Foo.bar();कॉल स्पष्ट रूप से अवैध है, और आप हमेशा उपयोग करेंगे Foo2.bar();।
इसे ध्यान में रखते हुए, एक स्थिर अमूर्त पद्धति का एकमात्र उद्देश्य इस तरह की विधि को लागू करने के लिए उपवर्गों को लागू करना होगा। आप शुरू में सोच सकते हैं इस बहुत गलत है, लेकिन अगर आप एक सामान्य प्रकार पैरामीटर है <E extends MySuperClass>यह इंटरफ़ेस के माध्यम से है कि गारंटी करने के लिए अच्छा होगा Eकर सकते हैं .doSomething()। ध्यान रखें कि टाइप इरेज़र जेनरिक के कारण केवल संकलन के समय ही मौजूद होते हैं।
तो, क्या यह उपयोगी होगा? हां, और शायद यही वजह है कि जावा 8 इंटरफेस में स्थिर तरीकों की अनुमति दे रहा है (हालांकि केवल एक डिफ़ॉल्ट कार्यान्वयन के साथ)। कक्षाओं में डिफ़ॉल्ट कार्यान्वयन के साथ सार स्थिर तरीके क्यों नहीं? केवल इसलिए कि डिफ़ॉल्ट कार्यान्वयन के साथ एक अमूर्त विधि वास्तव में एक ठोस विधि है।
कोई डिफ़ॉल्ट कार्यान्वयन के साथ सार / इंटरफ़ेस स्थिर तरीके क्यों नहीं? जाहिरा तौर पर, केवल इसलिए कि जावा जिस तरह से पहचानता है कि उसे किस कोड को निष्पादित करना है (मेरे उत्तर का पहला भाग)।
क्योंकि अमूर्त वर्ग एक OOPS अवधारणा है और स्थैतिक सदस्य OOPS का हिस्सा नहीं हैं ....
अब बात यह है कि हम इंटरफ़ेस में स्थैतिक पूर्ण विधियों की घोषणा कर सकते हैं और हम इंटरफ़ेस के अंदर मुख्य विधि की घोषणा करके इंटरफ़ेस निष्पादित कर सकते हैं
interface Demo
{
public static void main(String [] args) {
System.out.println("I am from interface");
}
}
एक अमूर्त स्थिर विधि होने का विचार यह होगा कि आप उस पद्धति के लिए उस विशेष सार वर्ग का सीधे उपयोग नहीं कर सकते हैं, लेकिन केवल पहले व्युत्पन्न को ही उस स्थैतिक विधि को लागू करने की अनुमति होगी (या जेनरिक के लिए: जेनेरिक का वास्तविक वर्ग उपयोग)।
इस प्रकार, आप उदाहरण के लिए एक छांटने योग्य सार वर्ग या यहां तक कि (ऑटो-) सार स्थैतिक विधियों के साथ इंटरफेस बना सकते हैं, जो क्रमबद्ध विकल्पों के मापदंडों को परिभाषित करता है:
public interface SortableObject {
public [abstract] static String [] getSortableTypes();
public String getSortableValueByType(String type);
}
अब आप एक छांटने योग्य वस्तु को परिभाषित कर सकते हैं जिसे मुख्य प्रकारों द्वारा क्रमबद्ध किया जा सकता है जो इन सभी वस्तुओं के लिए समान हैं:
public class MyDataObject implements SortableObject {
final static String [] SORT_TYPES = {
"Name","Date of Birth"
}
static long newDataIndex = 0L ;
String fullName ;
String sortableDate ;
long dataIndex = -1L ;
public MyDataObject(String name, int year, int month, int day) {
if(name == null || name.length() == 0) throw new IllegalArgumentException("Null/empty name not allowed.");
if(!validateDate(year,month,day)) throw new IllegalArgumentException("Date parameters do not compose a legal date.");
this.fullName = name ;
this.sortableDate = MyUtils.createSortableDate(year,month,day);
this.dataIndex = MyDataObject.newDataIndex++ ;
}
public String toString() {
return ""+this.dataIndex+". "this.fullName+" ("+this.sortableDate+")";
}
// override SortableObject
public static String [] getSortableTypes() { return SORT_TYPES ; }
public String getSortableValueByType(String type) {
int index = MyUtils.getStringArrayIndex(SORT_TYPES, type);
switch(index) {
case 0: return this.name ;
case 1: return this.sortableDate ;
}
return toString(); // in the order they were created when compared
}
}
अब आप एक बना सकते हैं
public class SortableList<T extends SortableObject>
जो प्रकारों को पुनः प्राप्त कर सकते हैं, एक प्रकार का चयन करने के लिए पॉप-अप मेनू का निर्माण कर सकते हैं और उस प्रकार से डेटा प्राप्त करके सूची का सहारा ले सकते हैं, साथ ही एक फ़ंक्शन को जोड़ सकते हैं, जब एक प्रकार का चयन किया गया हो, तो ऑटो कर सकते हैं में नई वस्तुओं को दर्ज करें। ध्यान दें कि SortableList का उदाहरण सीधे "T" की स्थिर विधि तक पहुंच सकता है:
String [] MenuItems = T.getSortableTypes();
एक उदाहरण का उपयोग करने के साथ समस्या यह है कि SortableList में अभी तक आइटम नहीं हो सकते हैं, लेकिन पहले से ही पसंदीदा सॉर्टिंग प्रदान करने की आवश्यकता है।
चेरियो, ओलाफ।
सबसे पहले, अमूर्त वर्गों के बारे में एक महत्वपूर्ण बिंदु - एक सार वर्ग को तत्काल नहीं किया जा सकता है ( विकी देखें )। इसलिए, आप एक अमूर्त वर्ग का कोई उदाहरण नहीं बना सकते हैं ।
अब, जिस तरह से जावा स्टैटिक विधियों से संबंधित है , वह उस वर्ग के सभी उदाहरणों के साथ विधि साझा करने से है।
इसलिए, यदि आप किसी वर्ग को तत्काल नहीं भेज सकते हैं, तो उस कक्षा में अमूर्त स्थिर तरीके नहीं हो सकते हैं क्योंकि एक अमूर्त विधि को बढ़ाया जाना चाहिए।
बूम।
जावा डॉक्टर के अनुसार :
एक स्थिर विधि एक विधि है जो उस वर्ग से जुड़ी होती है जिसमें इसे किसी वस्तु के बजाय परिभाषित किया जाता है। कक्षा का हर उदाहरण अपने स्थिर तरीकों को साझा करता है
जावा 8 में, डिफ़ॉल्ट तरीकों के साथ-साथ एक इंटरफ़ेस में स्थिर तरीकों की भी अनुमति है। इससे हमें अपने पुस्तकालयों में सहायक विधियों को व्यवस्थित करने में आसानी होती है। हम स्थिर तरीकों को एक अलग वर्ग के बजाय एक ही इंटरफ़ेस में एक इंटरफ़ेस के लिए विशिष्ट रख सकते हैं।
इसका एक अच्छा उदाहरण है:
list.sort(ordering);
के बजाय
Collections.sort(list, ordering);
स्थैतिक तरीकों का उपयोग करने का एक और उदाहरण भी डॉक्टर में ही दिया गया है:
public interface TimeClient {
// ...
static public ZoneId getZoneId (String zoneString) {
try {
return ZoneId.of(zoneString);
} catch (DateTimeException e) {
System.err.println("Invalid time zone: " + zoneString +
"; using default time zone instead.");
return ZoneId.systemDefault();
}
}
default public ZonedDateTime getZonedDateTime(String zoneString) {
return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
}
}
क्योंकि 'एब्सट्रैक्ट' का मतलब है कि विधि को ओवरराइड करना है और कोई 'स्टैटिक' तरीकों को ओवरराइड नहीं कर सकता।
नियमित तरीकों को अमूर्त किया जा सकता है जब उन्हें उपवर्गों द्वारा अधिग्रहित किया जाना चाहिए और कार्यक्षमता प्रदान की जाएगी। वर्ग की कल्पना करोFooBar1, Bar2, Bar3 आदि के द्वारा विस्तार किया गया है , इसलिए, प्रत्येक के पास अपनी आवश्यकताओं के अनुसार सार वर्ग का अपना संस्करण होगा।
अब, परिभाषा के अनुसार स्थिर विधियां वर्ग से संबंधित हैं, उनका कक्षा की वस्तुओं या उसके उपवर्गों की वस्तुओं से कोई लेना-देना नहीं है। उन्हें मौजूद होने की भी आवश्यकता नहीं है, उनका उपयोग कक्षाओं को तुरंत किए बिना किया जा सकता है। इसलिए, उन्हें तैयार रहने की जरूरत है और उप-वर्ग पर निर्भर नहीं हो सकता है कि वे उनमें कार्यक्षमता जोड़ सकें।
आप इसे जावा 8 में इंटरफेस के साथ कर सकते हैं।
यह इसके बारे में आधिकारिक दस्तावेज है:
https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
क्योंकि यदि कोई वर्ग एक अमूर्त वर्ग का विस्तार करता है तो उसे अमूर्त विधियों को ओवरराइड करना पड़ता है और यह अनिवार्य है। और चूंकि स्थैतिक विधियाँ संकलित समय पर हल की जाने वाली वर्ग विधियाँ हैं, जबकि अधिरोपित विधियाँ उदाहरण विधियाँ हैं जो रनटाइम पर हल की जाती हैं और गतिशील बहुरूपता का अनुसरण करती हैं।