Is it possible to override operator use in Objective-C?
For example
myClassInstance + myClassInstance
calls a custom function to add the two.
Operator overloading is not a feature of Objective-C. If two instances of your classes can be added together, provide a method and allow them to be added using that method:
Thing *result = [thingOne thingByAddingThing:thingTwo];
Or, if your class is mutable:
[thingOne addThing:thingTwo];
No, you can't do this in Objective-C.
You can do this now in Swift, a successor to objC. And since Objective-C and Swift are made to work together This could be interesting for you.
You may want to support subscripting for your object. Subscripting is not operator overloading, but it can be handy for a collection object. NSArray and NSDictionary both support subscripting. For example:
NSMutableArray *a = [NSMutableArray new];
a[0] = #"Hello";
The way to support index subscripting is to implement the following:
-(id)objectAtIndexedSubscript:(NSUInteger)idx;
-(void)setObject:(id)newObject atIndexedSubscript:(NSUInteger)idx];
I know this is an old question but I just wanted to leave this answer here for anybody in the future that might want to know if this is a possibility.
The answer is YES!
You'll have to use a variant of Objective-C called Objective-C++.
As an example, say you created a new Objective-C command-line tool project. In order to allow C++ functionality, you'll need to rename "main.m" to "main.mm". Afterwards, you can mix C++ code in with your Objective-C code in the same file. There are some limitations, but I've tested operator overloading and it seems to work perfectly fine with Objective-C objects as far as I can tell.
I've included sample source code to give you an idea of how to do it:
//main.mm
#import <Foundation/Foundation.h>
#include <iostream>
#include <string>
std::ostream &operator<<(std::ostream &os, NSString *s) {
os << [s UTF8String];
return os;
}
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSString *str = #"I'm an NSString!";
std::cout << str << std::endl;
}
return 0;
}
Here's my output after building and running this code:
I'm an NSString!
Program ended with exit code: 0
Hopefully this will be of help to somebody!
No, Objective-C does not support operator overloading.
First, operator overloading is evil. Second, C doesn't have operator overloading, and Objective-C is a proper superset of C, which only adds a handful of keywords and a messaging syntax.
That being said, if you're using Apple's development environment, you can use Objective-C++ instead of Objective-C, which gives you access to all of C++'s mistakes and misfeatures, including operator overloading. The simplest way to use Objective-C++ is just to change the extension on your implementation files from ".m" to ".mm"
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Operator overloading in C
If I have a struct:
typedef struct myStruct {
...
} myStruct;
myStruct myStructAdd(myStruct a, myStruct b);
I need something like this:
#define myStruct a + myStruct b myStructAdd(a, b)
// NOTE this code does NOT WORK. This is what the question is asking.
To make this syntax valid:
myStruct a;
myStruct b;
myStruct c = a + b;
Is there any way to use a #define to do this?
EDIT:
I'm not asking for alternatives to the + syntax. What I'm asking is if, and how, the preprocessor can be used to rewrite the plus syntax to standard C syntax on compile.
i.e. something like #define myStruct a + myStruct b myStructAdd(a, b) which turns myStructA + myStructB into myStructAdd(myStructA, myStructB) on compile.
Operator overloading simply isn't a feature of C or Objective-C. C++ allows you to define arbitrary behaviour for operators and custom types. In Objective-C, if two objects can be added together, then usually there is a method for that:
Foo *result = [foo1 fooByAddingFoo:foo2];
Or, if the class is mutable:
Foo *foo1 = [Foo fooWithBar:bar];
[foo1 addFoo:foo2];
If operator overloading is a must-have feature, use C++ instead, or use Objective-C++ (but keep in mind that C++ classes and Objective-C objects are totally and fundamentally different).
Edit:
The C proprocessor is conceptually very simple, and it knows very, very little about C's syntax, and nothing at all about C's types. If you wanted to overload an operator using the preprocessor, then it would have to learn every type (including custom types) used in your code, and it would have to perform static type checking in order to determine which function to invoke, and this is something that is way out of the scope of the preprocessor.
It's an interesting idea, but it's simply not possible.
There is no way for you to do that using the preprocessor. Also, as far as I known, there is no other feature that would provide this in objective C.
However, if you would use C++ (or objective-C++, which give you all features of both Objective C and C++) you could define an operator+, as follows:
struct myStruct
{
myStruct operator+(myStruct const & other)
{
return ...;
}
}
If you limit your question to the preprocessor then the answer is that it is impossible due to the fact that to define a macro that takes in arguments you have to have a parentheses macro like
#define __DO_STH(par1,par2)
Operator overloading the way you think of it does not use parentheses so you can not create any such macros
The only way to do that would be to make a simple parser which would be reading your code and whenever it encountered the structs you need being added with a plus sign spit out C code that replaces that with the function, but why do that and not use C++ where it's natively supported?
Also unless you are asking for purely academic purposes, it is my honest opinion that operator overloading always does more bad than good and is better avoided.
The only way I know is to use Objective-C++. To do this, give your implementation file the extension "mm" and you're good to go.
I've been learning Obj-C since getting a MBP about a month ago. I'm fairly comfortable with what I'm learning & things are slotting in to my rusty old brain pretty well. Except there's one thing I'm just not sure if I'm overlooking, or if just going over my head, or I'm looking for something that isn't there.
Most languages I've used have a way of slotting in an inline function call to simplify the coding, & I'm just not sure how this translates in Obj-C. Especially I'm referring to when the function being called is in a separate file, for the coding purposes of keeping similar functions together.
So far, the only way I've seen in Obj-C guides & tutorials is to create a class with methods & then instantiate that class (within the class you're working) to access the method in a [message]. Is this the way it's done in Obj-C? The only way? The best way for some reason? I know classes have their place in many languages & I use them myself, but I'm referring to simple little inline function calls where I usually wouldn't go to the trouble of creating a complete class.
To use a simple C++ console example of my point (only showing the .cpp files):
// example mainFile.cpp
#include <iostream>
#include "mainFile.h"
#include "functionsFile.h"
using namespace std;
void theMainFunction () {
int resultBeforeAltering = 100;
// alterTheResult() = simple inline function call I'm referring to
cout << "The result is " << alterTheResult(resultBeforeAltering);
}
.
// example functionsFile.cpp - could contain many similar functions
#include "functionsFile.h"
int alterTheResult (int resultToAlter) {
int alteredResult;
if (resultToAlter < 100) {
alteredResult = resultToAlter * 2;
} else {
alteredResult = resultToAlter * 3;
}
return (alteredResult);
}
Is there an equivalent approach to do alterTheResult() in Obj-C (assuming mainFunction() was an Obj-C method)?
I've seen reference to functions within Obj-C, but they seem to be C functions being referred to. C functions are not what I'm asking about here.
Thanks in advance, answers much appreciated.
Yes, the way to inline is to use C or C++ inlining -- that's perfectly legal (for C++, that will require compiling as ObjC++). An ObjC method will never be inlined (until LLVM produces a JIT compiler =p).
If you simply want to organize methods in another file, you may want to try an ObjC category:
// NSString_MONStuff.h
#interface NSString (MONStuff)
- (BOOL)mon_isPalindrome;
#end
// NSString_MONStuff.m
#implementation NSString (MONStuff)
- (BOOL)mon_isPalindrome { return ...; }
#end
Again, those will not be inlined.
You can also use C or C++ external functions or classes instead of categories for organization - the benefit is speed, size, reduced dependencies, and safety. The choice is yours, but there's no way to inline an objc method (it's a very dynamic langauge).
I´m trying to pass a reference of array of floats.
The problem is the call, because I´am developing for c but I want to make a call to an Objective C Function, Could anyone help me? How can I make the call?
There you have the code:
bool VideoCamera_Camera(float *buffer) {
[VideoCameraBinded VideoCamera_CameraUpdateBinded: buffer];
}
Thank you
I'm going to assume that VideoCameraBinded is an instance, and not a class. If I am mistaken, please let me know.
If you have a method defined on VideoCameraBinded's class, something like this:
- (void)VideoCamera_CameraUpdateBinded:(float *)buffer {
//...
}
then I don't know where your problem is coming from. Are you getting a specific error or some other issue?
If you have access to and can change the Objective-C code, add a C API there.
Otherwise, if you really can't change the Objective-C code you can use the Objective-C runtime directly, but this is discouraged:
#include <objc/runtime.h>
objc_msgSend(VideoCameraBinded, // receiver
sel_registerName("VideoCamera_CameraUpdateBinded:"), // selector
buffer); // comma separated list of arguments
You need to link to an Objective-C runtime library, usually libobjc:
$ clang mycode.c -lobjc
$ # or cc if you use GCC
If the Objective-C method expects an NSArray * instead of a float *, you can use Core Foundation with CFArrayRef. CFArrayRef and NSArray * are interchangeable, but CFArrayRef is a C type so you can use that. Same goes for CFNumberRef and NSNumber *, see Apple's documentation on this.
What is the parameter type for VideoCamera_CameraUpdateBinded:?
If its NSArray then you have to loop, create an array and send it like any other obj-c method. You'll have to store the floats in some kind of objects (e.g. NSNumber).
Otherwise, if the obj-c function is taking a float* then you should be good to go.
BTW, shouldn't you pass a bufferSize parameter too?
I am a little confused as to when it's best to use:
static NSString *AppQuitGracefullyKey = #"AppQuitGracefully";
instead of
#define AppQuitGracefullyKey #"AppQuitGracefully"
I've seen questions like this for C or C++, and I think what's different here is that this is specifically for Objective C, utilizing an object, and on a device like the iPhone, there may be stack, code space or memory issues that I don't yet grasp.
One usage would be:
appQuitGracefully = [[NSUserDefaults standardUserDefaults] integerForKey: AppQuitGracefullyKey];
Or it is just a matter of style?
Thanks.
If you use a static, the compiler will embed exactly one copy of the string in your binary and just pass pointers to that string around, resulting in more compact binaries. If you use a #define, there will be a separate copy of the string stored in the source on each use. Constant string coalescing will handle many of the dups but you're making the linker work harder for no reason.
See "static const" vs "#define" vs "enum". The main advantage of static is type safety.
Other than that, the #define approach introduces a flexibility of inline string concatenation which cannot be done with static variables, e.g.
#define ROOT_PATH #"/System/Library/Frameworks"
[[NSBundle bundleWithPath:ROOT_PATH#"/UIKit.framework"] load];
but this is probably not a good style :).
I actually would recommend neither, you should use extern instead. Objective-c already defines FOUNDATION_EXPORT which is more portable than extern, so a global NSString instance would look something like this:
.h
FOUNDATION_EXPORT NSString * const AppQuitGracefullyKey;
.m
NSString * const AppQuitGracefullyKey = #"AppQuitGracefully";
I usually put these in declaration files (such as MyProjectDecl.h) and import whenever I need.
There are a few differences to these approaches:
#define has several downsides, such as not being type safe. It is true that there are workarounds for that (such as #define ((int)1)) but what's the point? And besides, there are debugging disadvantages to that approach. Compilers prefer constants. See this discussion.
static globals are visible in the file they are declared.
extern makes the variable visible to all files. That contrasts with static.
Static and extern differ in visibility. It's also notable that neither of these approaches duplicates the string (not even #define) as the compiler uses String Interning to prevent that. In this NSHipster post they show proof:
NSString *a = #"Hello";
NSString *b = #"Hello";
BOOL wtf = (a == b); // YES
The operator == returns YES only if the two variables point at the same instance. And as you can see, it does.
The conclusion is: use FOUNDATION_EXPORT for global constants. It's debug friendly and will be visible allover your project.
After doing some search (this question/answer among other things) I think it is important to say that anytime when you are using string literal #"AppQuitGracefully" constant string is created, and no matter how many times you use it it will point to the same object.
So I think (and I apologize me if I'm wrong) that this sentence in above answer is wrong: If you use a #define, there will be a separate copy of the string stored in the source on each use.
I use static when I need to export NSString symbols from a library or a framework. I use #define when I need a string in many places that I can change easily. Anyway, the compiler and the linker will take care of optimizations.
USING #define :
you can't debug the value of identifier
work with #define and other macros is a job of Pre-Processor,
When you hit Build/Run first it will preprocess the source code, it will work with all the macros(starting with symbol #),
Suppose, you have created,
#define LanguageTypeEnglish #"en"
and used this at 2 places in your code.
NSString *language = LanguageTypeEnglish;
NSString *languageCode = LanguageTypeEnglish;
it will replace "LanguageTypeEnglish" with #"en", at all places.
So 2 copies of #"en" will be generated.
i.e
NSString *language = #"en";
NSString *languageCode = #"en";
Remember, till this process, compiler is not in picture.
After preprocessing all the macros, complier comes in picture, and it will get input code like this,
NSString *language = #"en";
NSString *languageCode = #"en";
and compile it.
USING static :
it respects scope and is type-safe.
you can debug the value of identifier
During compilation process if compiler found,
static NSString *LanguageTypeRussian = #"ru";
then it will check if the variable with the same name stored previously,
if yes, it will only pass the pointer of that variable,
if no, it will create that variable and pass it's pointer, next time onwards it will only pass the pointer of the same.
So using static, only one copy of variable is generated within the scope.
I've reading in several post and in Apple's code guidelines that in Objective-C String constants should be defined as extern NSString *const MY_CONSTANT; and that the #define directive should be avoided. Why is that? I know that #define is run at precompile time but all string will share the same memory address. The only advantage I read was that if the constant must be updated or changed you don't have to recompile your entire project. So that i s the reason why #define should be avoided?
Thanks
UPDATE: In this case is good to use a #define or there is a better approach?
/* Constants Definition */
#define SERVER_URL #"http://subdomain.domain.edu.ar/Folder/"
NSString *const ServerURL = SERVER_URL;
NSString *const LoginURL = SERVER_URL#"welcome.asp";
NSString *const CommandURL = SERVER_URL#"com.asp";
A practical reason to use the constant as opposed to the definition is that you can do direct comparisons (using ==) instead of using isEqual:. Consider:
NSString * const kSomeStringConstant = #"LongStringConstantIsLong";
...
[someArray addObject:kSomeStringConstant];
if ([someArray lastObject] == kSomeStringConstant)
{
...
}
This would work, since the == comparison would be comparing identical const pointers to a single NSString object. Using #define, however:
#define STRING_CONSTANT #"MacrosCanBeEvil";
...
[SomeArray addObject:STRING_CONSTANT]; // a new const `NSString` is created
if ([someArray lastObject] == STRING_CONSTANT) // and another one, here.
{
...
}
This would not work out, since the two strings would have unique pointers. To compare them effectively, you would have to do a character-by-character comparison using isEqual:
if ([[someArray lastObject] isEqual:STRING_CONSTANT])
{
...
}
This can be far more costly in terms of execution time than the simple == comparison.
Another motivation could be the size of the executable itself. The #defined constant would actually appear, in place, wherever it was used in the code. This could mean that the string appears many times in your executable. In contrast, the constant should (with modern compilers) be defined only once, and all further usages would make reference to the pointer to that one definition.
Now, before anyone yells at me for premature optimization, consider that the two approaches are almost identical in terms of implementation, but the const pointer method is far superior in terms of code size and execution time.
It's not necessarily guaranteed that there will only be one NXConstantString object for a given string literal in an entire application. It seems pretty likely that different compilation units might have different objects for the same constant string. For example, if somebody writes a plugin, one constant string will be generated for occurrences of that NSString literal in the plugin and one will be generated for occurrences in the host application, and these will not be pointer-equal.
The best argument I have heard is that const strings show up in the debugger, whereas macros do not.
static NSString * const SERVER_URL = #"http://subdomain.domain.edu.ar/Folder/";
As far as I know, #define only lets you define C-style string constants. To create a constant NSString object, you have to declare it in the header, and then give it a value in one of your .m files.
Header file:
extern NSString *MyConstantString;
Main file:
NSString *MyConstantString = #"String value";