it-swarm.com.de

Wie würden Sie eine einfache "min" -Methode in obj-c definieren?

Ich möchte eine min und max Methode in einer Utils Klasse definieren.

@interface Utils

int min(int a, int b);
int max(int a, int b);

@end

Aber ich möchte keine benannten Parameter haben. Es wäre eine zu schwere Notation. Ich wollte die C-Definition verwenden. Aber dann [Utils min(a, b)] als Anruf funktioniert nicht. Was ist mein problem

Vielen Dank im Voraus für jede Hilfe

21
Fred Polack

Da Sie die OS X-Implementierung von Objective-C nicht verwenden, haben Sie möglicherweise keinen Zugriff auf die vordefinierten MIN- und MAX-Makros.

Diese können Sie selbst definieren als

#define MIN(a,b)    ((a) < (b) ? (a) : (b))
#define MAX(a,b)    ((a) > (b) ? (a) : (b))

Es gibt wahrscheinlich einen besseren Weg, sie zu definieren, aber diese werden die einfachen Makros für Ihre Verwendung erstellen. Sie können sie in jede gängige .h-Datei einfügen, die Ihre Klassen normalerweise gemeinsam nutzen.

18
Brandon Bodnar

Es ist bereits als Makro definiert.

MIN(a, b)

MAX(a, b)

Sie müssen diese nicht neu definieren.

62
Mongus Pong

Es gibt ein ernstes Sicherheitsproblem mit der von Brandon Bodnár veröffentlichten Lösung (die zum Zeitpunkt dieses Schreibens als gültige Lösung markiert ist).

Hier beschriebenes Problem: http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Min-and-Max.html Und die (gültige und sichere) Lösung dafür: http: //gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Typeof.html

Überzeugen Sie sich selbst:

#include <stdio.h>

#define NAIVE_MAX(a,b) (a > b ? a : b)

#define NAIVE_MIN(a,b) (a < b ? a : b)

#if !defined MAX
#define MAX(a,b) \
({ __typeof__ (a) __a = (a); \
__typeof__ (b) __b = (b); \
__a > __b ? __a : __b; })
#endif

#if !defined MIN
#define MIN(a,b) \
({ __typeof__ (a) __a = (a); \
__typeof__ (b) __b = (b); \
__a < __b ? __a : __b; })
#endif

int main (int argc, const char * argv[]) {
    int a = 3;
    int b = 5;

#pragma mark NON-FATAL CASES:
    printf("NAIVE_MAX(%d, %d) => %d\n", a, b, NAIVE_MAX(a, b));
    printf("NAIVE_MIN(%d, %d) => %d\n", a, b, NAIVE_MIN(a, b));

    printf("MAX(%d, %d) => %d\n", a, b, MAX(a, b));
    printf("MIN(%d, %d) => %d\n", a, b, MIN(a, b));

    printf("\nEverything fine so far...\n\n");

#pragma mark FATAL CASES:
    //cache:
    int _a = a;
    int _b = b;
    printf("NAIVE_MAX(%d++, %d++) => %d\n", _a, _b, NAIVE_MAX(a++, b++));

    //reset:
    a = _a;
    b = _b;
    printf("NAIVE_MIN(%d++, %d++) => %d\n", _a, _b, NAIVE_MIN(a++, b++));

    //reset:
    a = _a;
    b = _b;
    printf("NAIVE_MAX(++%d, ++%d) => %d\n", _a, _b, NAIVE_MAX(++a, ++b));

    //reset:
    a = _a;
    b = _b;
    printf("NAIVE_MIN(++%d, ++%d) => %d\n", _a, _b, NAIVE_MIN(++a, ++b));

    printf("\nOuch, this doesn't look right at all!\n\n");

#pragma mark NON-FATAL CASES:
    //reset:
    a = _a;
    b = _b;
    printf("MAX(%d++, %d++) => %d\n", _a, _b, MAX(a++, b++));

    //reset:
    a = _a;
    b = _b;
    printf("MIN(%d++, %d++) => %d\n", _a, _b, MIN(a++, b++));

    //reset:
    a = _a;
    b = _b;
    printf("MAX(++%d, ++%d) => %d\n", _a, _b, MAX(++a, ++b));

    //reset:
    a = _a;
    b = _b;
    printf("MIN(++%d, ++%d) => %d\n", _a, _b, MIN(++a, ++b));

    printf("\nAh, much better now.\n\n");

    return 0;
}

Konsolenprotokoll:

NAIVE_MAX(3, 5) => 5
NAIVE_MIN(3, 5) => 3
MAX(3, 5) => 5
MIN(3, 5) => 3

Everything fine so far...

NAIVE_MAX(3++, 5++) => 6
NAIVE_MIN(3++, 5++) => 4
NAIVE_MAX(++3, ++5) => 7
NAIVE_MIN(++3, ++5) => 5

Ouch, this doesn't look right at all!

MAX(3++, 5++) => 5
MIN(3++, 5++) => 3
MAX(++3, ++5) => 6
MIN(++3, ++5) => 4

Ah, much better now.

Also benutze niemals die naive Implementierung wie im obigen Code (und wie von Brandon Bodnár vorgeschlagen, sorry buddy;)), wenn du solche schlimmsten Fälle vermeiden willst.

29
Regexident

Dies ist wahrscheinlich keine gute Idee für diese spezielle Anwendung, aber es ist möglich Objective-C-Methoden mit Parametern "ohne Namen" oder vielmehr mit Namen mit der Länge Null zu schreiben:

+ min:(int)a :(int)b;
...
[Utils min:a :b]

(Der Selektor wäre @selector(min::).)

6
Kevin Reid

Objective-C-Klassenmethoden verwenden benannte Parameter (Punkt). So ist es halt.

Warum nicht eine globale, freie Funktion daraus machen? Sie sollten keine Utils-Klasse für diese Art von Dingen benötigen.

Wenn Sie den globalen Namespace nicht überladen möchten, können Sie Objective-C++ verwenden (alle .m-Dateien in .mm umbenennen) und ihn in einen Namespace einfügen.

1

In einer Vorlagendatei mit dem Namen "XXIntegerMath.h" legen Sie Folgendes ab ...

#import <Foundation/Foundation.h>

static inline NSInteger imax(NSInteger a, NSInteger b) {
    return  a > b ? a : b;
}

static inline NSInteger imin(NSInteger a, NSInteger b) {
    return  a < b ? a : b;
}

Dann in deiner Objective-C-Klasse ...

#import "XXIntegerMath.h"
NSInteger minValue = imin(someValue, someOtherValue);

Es leidet nicht unter den von Regexident beschriebenen Problemen.

0
TJez