2011-09-22 14 views
9

कभी कभी हम एक वैकल्पिक पैरामीटरएक वैकल्पिक बूलियन चर

function doSomething(foo:Integer; bar:TObject=nil) 
begin 
    if bar <> nil then // do something optional with bar 
    .... 
end 

मैं एक बूलियन साथ बराबर कैसे करते हैं चाहते हैं, कि मुझे दो बूलियन मूल्यों और "कोई मूल्य" के बीच अंतर करने की अनुमति देता है दर्रा?

function doSomething(foo:Integer; bar:Boolean=nil) // Won't compile 
begin 
    if bar <> nil then // do something optional with bar 
end 

स्पष्ट रूप से यह संकलित नहीं होगा क्योंकि एक बूलियन शून्य नहीं हो सकता है।

असल में, मैं तीन संभावित राज्यों के साथ एक पैरामीटर चाहता हूं; सच, झूठा या "अनिर्दिष्ट"।

उत्तर

18

आप इस दूसरी तरह के, अधिक भार का उपयोग कर सकते हैं:

:

function doSomething(foo:Integer): Boolean; overload; 
begin 
    // do something without bar 
end; 

function doSomething(foo:Integer; bar:Boolean): Boolean; overload 
begin 
    // do something optional with bar 
end; 

तो फिर तुम यह doSomething(1) के रूप में उपयोग कर सकते हैं, साथ ही doSomething(1, true)

के रूप में अपने उदाहरण का उपयोग करना, यह के बराबर होगी

function doSomething(foo:Integer; bar:Boolean=nil): Boolean; // Won't compile 
begin 
    if bar <> nil then 
     // do something optional with bar 
    else 
     // do something without bar 
end; 
+0

+1 यह प्राप्त करने का यह सबसे अच्छा तरीका है, आईएमओ। तीन राज्य हैं: 'कुछ करो (1)', 'कुछ करो (1, सही)' और 'कुछ करो (1, झूठा) '। –

+0

@ रुडी, हाँ, लेकिन केवल इसलिए कि ओपी ने * बूलियन * पैरामीटर के साथ काम करने की आवश्यकता निर्दिष्ट की है। अन्यथा मुझे लगता है कि 3 अलग-अलग कोड पथ एक 3 राज्य परिवर्तनीय (जैसे ग्रेग हेगिल के थ्रीस्टेटबोलियन उदाहरण) का उपयोग करके अधिक कुशलतापूर्वक विभेदित होते हैं। – Sam

+0

@ रुडी, यह बेहतर जवाब क्या बनाता है कि यह ओपी की वाक्य का अनुपालन करता है "कभी-कभी हम एक वैकल्पिक पैरामीटर चाहते हैं", यह तथ्य नहीं कि तीन राज्य समर्थित हैं (क्योंकि दोनों उत्तरों ऐसा करते हैं)। IMO। – Sam

4

बूलियन प्रकार के मान केवल सत्य या गलत हो सकते हैं। , यह सच है झूठा, और अनिर्दिष्ट:: आप तीन राज्यों है कि अपनी खुद की प्रकार परिभाषित कर सकते

type ThreeStateBoolean = (True, False, Unspecified); 

या, आप एक बूलियन करने के लिए एक सूचक पारित कर सकते हैं:

type PBoolean = ^Boolean; 

function doSomething(bar: PBoolean = nil) 
begin 
    if bar <> nil then 
     // do something with bar^ 
end 

एक करने के लिए एक सूचक पासिंग आप इसे कॉल करने के तरीके के आधार पर बूलियन अजीब हो सकते हैं।

+0

केवल आपके उत्तर का पहला भाग सही है, आप इस तरह के फ़ंक्शन को डेल्फी में घोषित नहीं कर सकते हैं, आपको 'PBoolean' जैसे पैरामीटर में पूर्वनिर्धारित प्रकारों का उपयोग करना चाहिए, इसलिए प्रक्रिया की तरह कुछ होना चाहिए Something2 (बार: PBoolean = शून्य); ' – RRUZ

+0

धन्यवाद, मैं इसे बदल दूंगा। यह बहुत लंबा समय रहा है क्योंकि मैंने पास्कल में कोड किया है ... –

+3

टाइप थ्रीस्टेटबोलियन = (सही, गलत, निर्दिष्ट नहीं); ध्यान दें कि आप वास्तव में सिस्टम बूलियन ट्रू और झूठी घोषणाओं को ओवरराइट किए बिना सही और गलत का उपयोग नहीं कर सकते हैं। यह संकलन त्रुटियों को देगा जहां आप वास्तव में बूलियन का उपयोग करते हैं। टीटीआरयू, टीएफएलएसई, निर्दिष्ट नहीं होगा। – HMcG

0

या ... आप एक इंटीजर का उपयोग कर सकते हैं और इसे आवश्यकतानुसार एक बूलियन में डाल सकते हैं। झूठी के लिए 0 का प्रयोग करें, सत्य के लिए 1, और -1 "शून्य" के लिए। वैसे भी आप इसे टुकड़ा करते हैं, आप जो भी चाहते हैं उसे करने के लिए आप एक बूलियन वैरिएबल का उपयोग नहीं कर सकते हैं, आपको लिंक्सनेक के सुझाव के रूप में एक और प्रकार या पैरामीटर के हेरफेर की आवश्यकता होगी।

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

4

एक और विकल्प (यदि आपके पास डेल्फी के लिए अपेक्षाकृत आधुनिक संस्करण है) तो इसे रिकॉर्ड के रूप में कार्यान्वित करना है, जिसमें बुलियन मूल्यों से और उसके लिए निहित रूपांतरण शामिल है। ऑपरेटर अधिभार के साथ, आप 3-राज्य तर्क भी सक्षम कर सकते हैं। यदि आपको आवश्यकता होती है तो यह ओवरकिल होता है, लेकिन यदि आपको तीन-राज्य तर्क प्रणाली की आवश्यकता होती है तो यह बहुत अच्छी तरह से काम करता है, खासकर जब आप इसे बूलियन मान निर्दिष्ट कर सकते हैं। 3-राज्य से 2-राज्य विचारों के असाइनमेंट से सावधान रहें। नीचे दिया गया उदाहरण बूलियन < - 'ट्रोलियन' असाइनमेंट में झूठा असाइन करता है जहां डेलीफी में एक असाइन किए गए बूलियन के अनुसार, ट्रोलियन टीएनआईएल है, लेकिन स्पष्ट जटिलताओं हैं।

कृपया ध्यान दें कि यह किसी भी माध्यम से पूर्ण या कुशल कार्यान्वयन नहीं है, यह संभव है कि यह संभवतः अभियोग करने के लिए एक डेमो है। संयोग से, जेरोइन प्लूइमर द्वारा निरर्थक प्रकारों पर एक अच्छा CodeRage vidoe है। This प्रश्न एक लिंक प्रदान करता है।

unit UnitTroolean; 

interface 

type 

    TTroolean = record 
    private type 
     TThreeState = (TTrue = 1, TFalse = 0, TNil = -1); 

    var 
     fThreeState: TThreeState; 
    public 
     function AsString: string; 
     class operator Implicit(Value: boolean): TTroolean; 
     class operator Implicit(Value: TTroolean): boolean; 
     class operator Implicit(Value: TThreeState): TTroolean; 
     class operator Implicit(Value: TTroolean): TThreeState; 
     class operator LogicalAnd(Left, Right: TTroolean): TTroolean; 
     class operator LogicalOr(Left, Right: TTroolean): TTroolean; 
     class operator LogicalNot(Value: TTroolean): TTroolean; 
    end; 

implementation 

{ TRoolean } 

class operator TTroolean.Implicit(Value: boolean): TTroolean; 
begin 
    if Value then 
    result.fThreeState := TTrue 
    else 
    result.fThreeState := TFalse; 
end; 

class operator TTroolean.Implicit(Value: TTroolean): boolean; 
begin 
    if not(Value.fThreeState = TNil) then 
    result := (Value.fThreeState = TTrue) 
    else 
    result := false; 
end; 

class operator TTroolean.Implicit(Value: TThreeState): TTroolean; 
begin 
    result.fThreeState := Value; 
end; 

class operator TTroolean.Implicit(Value: TTroolean): TThreeState; 
begin 
    result := Value.fThreeState; 
end; 

class operator TTroolean.LogicalAnd(Left, Right: TTroolean): TTroolean; 
begin 
    if (Left.fThreeState = TNil) or (Right.fThreeState = TNil) then 
    result.fThreeState := TNil 
    else if ((Left.fThreeState = TTrue) and (Right.fThreeState = TTrue)) then 
    result.fThreeState := TTrue 
    else 
    result.fThreeState := TFalse; 
end; 

class operator TTroolean.LogicalNot(Value: TTroolean): TTroolean; 
begin 
    begin 
    case value.fThreeState of 
    TNil: result.fThreeState:= TNil; 
    TTrue: result.fThreeState:= TFalse; 
    TFalse: result.fThreeState:= TTrue 
    end; 
    end; 

end; 

class operator TTroolean.LogicalOr(Left, Right: TTroolean): TTroolean; 
begin 
    if (Left.fThreeState = TNil) or (Right.fThreeState = TNil) then 
    result.fThreeState := TNil 
    else if ((Left.fThreeState = TTrue) or (Right.fThreeState = TTrue)) then 
    result.fThreeState := TTrue 
    else 
    result.fThreeState := TFalse; 
end; 

function TTroolean.AsString: string; 
begin 
    case ord(fThreeState) of 
    1: 
     result := 'TTrue'; 
    0: 
     result := 'TFalse'; 
    -1: 
     result := 'TNil'; 
    end; 
end; 

end. 

और उपयोग

program ThreeStateLogicTest; 

{$APPTYPE CONSOLE} 

uses 
    SysUtils, 
    UnitTroolean in 'UnitTroolean.pas'; 

var 
    ABoolean: boolean; 
    ATroolean, Anothertroolean, AThirdTroolean: TTroolean; 

begin 

    try 
    { TODO -oUser -cConsole Main : Insert code here } 

    write('Boolean:', BoolToStr(ABoolean, true), #10#13); 
    write(#10#13); 

    ATroolean := TFalse; 
    ABoolean := true; 
    ATroolean := ABoolean; 

    write('Boolean:', BoolToStr(ABoolean, true), #10#13); 
    write('Troolean:', ATroolean.AsString, #10#13); 
    write('Troolean as Boolean:', BoolToStr(ATroolean, true), #10#13); 
    write(#10#13); 

    ATroolean := TTrue; 
    ABoolean := false; 
    ATroolean := ABoolean; 

    write('Boolean:', BoolToStr(ABoolean, true), #10#13); 
    write('Troolean:', ATroolean.AsString, #10#13); 
    write('Troolean as Boolean:', BoolToStr(ATroolean, true), #10#13); 
    write(#10#13); 

    ABoolean := false; 
    ATroolean := TTrue; 
    ABoolean := ATroolean; 

    write('Boolean:', BoolToStr(ABoolean, true), #10#13); 
    write('Troolean:', ATroolean.AsString, #10#13); 
    write('Troolean as Boolean:', BoolToStr(ATroolean, true), #10#13); 
    write(#10#13); 

    ABoolean := true; 
    ATroolean := TFalse; 
    ABoolean := ATroolean; 

    write('Boolean:', BoolToStr(ABoolean, true), #10#13); 
    write('Troolean:', ATroolean.AsString, #10#13); 
    write('Troolean as Boolean:', BoolToStr(ATroolean, true), #10#13); 
    write(#10#13); 

    ABoolean := false; 
    ATroolean := Tnil; 
    ABoolean := ATroolean; 

    write('Boolean:', BoolToStr(ABoolean, true), #10#13); 
    write('Troolean:', ATroolean.AsString, #10#13); 
    write('Troolean as Boolean:', BoolToStr(ATroolean, true), #10#13); 
    write(#10#13); 

    ABoolean := true; 
    ATroolean := Tnil; 
    ABoolean := ATroolean; 

    write('Boolean:', BoolToStr(ABoolean, true), #10#13); 
    write('Troolean:', ATroolean.AsString, #10#13); 
    write('Troolean as Boolean:', BoolToStr(ATroolean, true), #10#13); 
    write(#10#13); 

    ATroolean := TTrue; 
    Anothertroolean := false; 

    AThirdTroolean := ATroolean and Anothertroolean; 
    write('And:', AThirdTroolean.AsString, #10#13); 

    AThirdTroolean := ATroolean or Anothertroolean; 
    write('Or:', AThirdTroolean.AsString, #10#13); 

    ATroolean := TNil; 
    Anothertroolean:= not ATroolean; 
    write('Not TNil:', Anothertroolean.AsString, #10#13); 

    ATroolean := TTrue; 
    Anothertroolean:= not ATroolean; 
    write('Not Ttrue:', Anothertroolean.AsString, #10#13); 

    ATroolean := Tfalse; 
    Anothertroolean:= not ATroolean; 
    write('Not Tfalse:', Anothertroolean.AsString, #10#13); 



    readln; 

    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 

end. 
+0

मुझे यह भी पता नहीं था कि डेल्फी ऑपरेटर ओवरलोडिंग था। – awmross

0

स्पष्ट तरीका enumeration (यानी enumerated type) का उपयोग करने का एक उदाहरण।

यह पहले से ही the Greg Hewgill's answer में दिखाया गया है - लेकिन गलत तरीके से, आपको पूर्वनिर्धारित false और true का उपयोग गणना पहचानकर्ताओं के रूप में नहीं करना चाहिए। और the HMcG's answer के भीतर - लेकिन रैपर प्रकार के भीतर (अधिक जटिल उदाहरण)। मैं कुछ लिखने का सुझाव देता हूं: type TTrilean = (triFalse, triTrue, triNull);

वैकल्पिक रूप से, यदि आप अपने प्रोजेक्ट में वीसीएल मॉड्यूल लाने में कोई फर्क नहीं पड़ता है, तो आप मौजूदा TCheckBoxStateStdCtrls मॉड्यूल से टाइप कर सकते हैं।


इसके अतिरिक्त आप the Serhii Kheilyk's answer प्रति आवरण कार्यों लिख सकते हैं:

procedure DoSomething(Foo: Integer; Bar: TTrilean); overload; 
begin 
    … //main code 
end; 

procedure DoSomething(Foo: Integer; Bar: Boolean); overload; 
const 
    Trileans: array[Boolean] of TTrilean = (triFalse, triTrue); 
begin 
    DoSomething(Foo, Trileans[Bar]); 
end; 

procedure DoSomething(Foo: Integer); overload; 
begin 
    DoSomething(Foo, triNull); 
end; 

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


नोट्स:
1. मुझे लगता है कि (यकीन नहीं), औपचारिक आप type TMyType = (False, True, Unspecified); लिख सकते हैं, False के रूप में और True नहीं आरक्षित शब्द हैं। लेकिन यह आपकी False और True प्रकार Boolean के उपयोग तक पहुंच जाएगा (इसके बाद आपको उन्हें और System.True के रूप में संदर्भित करना होगा)। और यह तीसरे पक्ष-संकलक-संगत नहीं है (उदा। एफपीसी इसे अनुमति नहीं देगा)।

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