2014-05-13 8 views
5

मैं एक सामान्य लैम्ब्डा एक विधि को लागू है और यह एक अतिरिक्त लाभ के रूप में toString है फिर से परिभाषित करने नहीं करना चाहती। मैं चाहता हूं कि लैम्ब्डा अभिव्यक्ति केवल टूस्ट्रिंग विधि को लागू करे। मुझे पता है कि मैं इसे बहुत अच्छी तरह से व्यक्त नहीं कर रहा हूं लेकिन मुझे यकीन है कि आप मुझे इस उदाहरण के साथ समझेंगे।लैम्बडा अभिव्यक्ति को जावा 8 में स्ट्रिंग को परिभाषित करने के लिए कैसे करें?

public class LambdaToStringTest { 

    public interface ToStringInterface { 
     public abstract String toString(); 
    } 

    public static void main(String[] args) { 
     print("TRACE: %s", (ToStringInterface)()->someComputation()); // <<-- ERROR: The target type of this expression must be a functional interface 
    } 

    private static void print(String format, Object... args) { 
     System.out.println(String.format(format, args)); 
    } 

} 

यह कम्पाइल अगर मैं विधि का नाम बदलने, लेकिन फिर यह toString पर हावी नहीं होता तो प्रिंट विधि मुद्रित नहीं होगा क्या उम्मीद है।

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

+0

मैं यह नहीं पूछ रहा हूँ: http://stackoverflow.com/questions/16544583/can-i-override-tostring- विधि-का-कार्यात्मक-इंटरफेस-इन-जेडीके 8-प्रयोग-लैम्बडास मैं केवल स्ट्रिंग को लागू करना चाहता हूं। – aalku

उत्तर

5

लघु जवाब कर रहा हूँ, आप नहीं कर सकते। @FunctionalInterface एस का उपयोग Object से "ओवरराइड" विधियों के लिए नहीं किया जा सकता है।

आप Formattable तथापि लागू कर सकते हैं, एक आभासी विस्तार विधि के साथ। नोट: नीचे दिए गए कोड untested है:

@FunctionalInterface 
public interface ToStringInterface 
    extends Formattable 
{ 
    String asString(); 

    @Override 
    default void formatTo(Formatter formatter, int flags, int width, int precision) 
    { 
     formatter.format("%s", this); 
     // Or maybe even better: 
     formatter.out().append(this.asString()); 
    } 
} 

मैं इस समाधान का प्रस्ताव जब से तुम String.format() जो इस इंटरफेस का उपयोग करता है का उपयोग कर रहे हैं।

या आप केवल अपने स्वयं के इंटरफेस को परिभाषित कर सकते हैं। या यहाँ तक कि इस इंटरफेस जो .asString() में .toString() कॉल के लिए एक आवरण लिखें। विकल्प कई हैं।

+0

मुझे नहीं लगता कि आपको इसका उपयोग करना चाहिए। एक इंटरफ़ेस में स्ट्रिंग को लैम्ब्डा द्वारा कार्यान्वित किया जाना चाहिए क्योंकि यह बेकार जानकारी प्रिंट करेगा। – aalku

+1

खैर, यह तुम्हारी पसंद है, मैं और अधिक नहीं कह सकता;) या हो सकता है lambdas सिर्फ तुम क्या करने की कोशिश कर रहे हैं क्या के लिए अनुकूलित नहीं कर रहे हैं। वैसे भी, आपके पास समाधान का मेरा विचार है। – fge

+1

ऐसा लगता है जैसे आप खुद को उलझन में डालते हैं। आखिरी पंक्ति में यह 'this.asString()' होना चाहिए। इस स्ट्रिंग() 'के बजाय यह आपके उत्तर का पूरा बिंदु है कि लैम्ब्डा' toString' की बजाय 'asString' लागू करेगा। – Holger

2

जैसा कि फेज इंगित करता है, इंटरफेस ऑब्जेक्ट क्लास (टूस्ट्रिंग, बराबर, हैशकोड) से विधियों की घोषणा नहीं कर सकता है।

मुझे लगता है कि होल्डर आपको प्रदायक को इंगित करने में सही है, और मुझे लगता है कि आलसी लॉग मूल्यांकनकर्ता बनाने के आपके निर्दिष्ट उद्देश्य को देखते हुए, आपको केवल अपनी प्रिंट विधि के अंदर कास्टिंग करना चाहिए।

private static void print(String format, Object... args) { 
    for (int i = 0; i < args.length; i++) { 
     if (args[i] instanceof Supplier) { 
      args[i] = ((Supplier<?>)args[i]).get(); 
     } 
    } 
    System.out.println(String.format(format, args)); 
} 

private static <T> Supplier<T> supply(Supplier<T> supplier) { 
    return supplier; 
} 

private static class Example { 

    private static String someString() { 
     return "hello"; 
    } 

    private static Boolean someBoolean() { 
     return true; 
    } 
} 

public static void main(String[] args) { 

    print("TRACE: %s; %s; %s", 
     supply(Example::someString), 
     supply(Example::someBoolean), 
     "extra"); 
} 
+0

कोस्टर विधि 'आपूर्ति' एक अच्छा विचार है, लेकिन हो सकता है कि मैं उस ऑब्जेक्ट से स्ट्रिंग को मुद्रित करना चाहूंगा जो प्रदायक लागू करता है, इसलिए मैं बेहतर कस्टम इंटरफ़ेस का उपयोग करता हूं। – aalku

1

functionals को बहुत शीघ्र उनके प्रकार पता करने की जरूरत है, जिसका अर्थ आप डाले एक टन होगा: अपने प्रिंट कॉल की वाक्य रचना के साथ मदद करने के लिए, आप एक उपयोगिता विधि है कि अनिवार्य रूप से आप के लिए डाली करता है बना सकते हैं यदि आप अपने मूल विचार के बहुत करीब रहने का प्रयास करते हैं तो ToStringInterface को। कलाकारों के बजाय, आप एक स्थिर विधि को कॉल कर सकते हैं।

static Object asString(Supplier<String> string){ 
    return new Object(){ 
     public String toString(){ 
      return string.get(); 
     } 
    }; 
}    

public static void main(String[] args) { 
    print("TRACE: %s", asString(()->someComputation())); 
} 

ईमानदारी हालांकि, होल्गर की टिप्पणी मुझे क्या करना होता है -

void print(String pattern, Supplier<?>... args); 
संबंधित मुद्दे