is self not completely interchangeable with this in C++?
It seems to work with message passing ([ self sayHi ] would work within any method there).
I don't quite understand why I can't use self to access private members of an object (in the example below, I show I can't use self.width)
#import <Foundation/Foundation.h>
// Write an Objective-C class
#interface Rectangle : NSObject
{
int width ;
}
-(int)getWidth;
-(void)setWidth:(int)w;
-(void)sayHi;
-(void)sayHi:(NSString*)msg ;
#end
#implementation Rectangle
-(int)getWidth
{
// <b>return self.width ; // ILLEGAL, but why?</b>
// why can't I return self.width here?
// why does it think that's a "method"?
return width ;
}
-(void)setWidth:(int)w
{
// <b>self.width = w ; // ILLEGAL</b>
// again here, I CAN'T do self.width = w ;
width = w ;
}
-(void)sayHi
{
puts("hi");
}
-(void)sayHi:(NSString*)msg
{
printf( "Hi, and %s\n", [ msg UTF8String ] ) ;
}
#end
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Rectangle* r = [ Rectangle alloc ] ;
[ r sayHi ] ;
[ r setWidth:5 ] ;
printf( "width is %d\n", [ r getWidth ] ) ;
[pool drain];
return 0;
}
The other answers are almost correct, but not quite.
In Objective-C, no object [save for Blocks, but that is a very very special case] are ever on the stack. Thus, self.width doesn't make sense.
However, self->width does work. Since self is a reference to what is effectively a structure allocated on the heap, using the -> operator to get at the member variables makes sense.
But, in the context of Objective-C, it generally doesn't make sense, either. That is, Objective-C generally assumes a philosophy of preserving encapsulation. That is, you don't generally reach into an object and muck with the instance variables -- the internal state -- directly. Instead, you use the accessors to get/set the state. By doing so, the object (and subclasses) can customize getter/setter behavior, as needed. (This includes such mechanisms as Key-Value Observing and Key-Value Coding).
That self.width happens to equate to [self width] or [self setWidth: ...something...] is fallout from the above. That is, the . operator for accessing members of Objective-C class instances was not otherwise used and could be overloaded as a short hand for property access.
However, there is little difference between property access and invoke the getter/setter method. Thus, dot notation is synonymous with method invocation.
Within the context of your code, instance variables are transparently accessible within your classes implementation and without prefix.
Thus, you would use width = 5.0; instead of self.width = 5.0;, typically. Of course, the latter does equate to a method call with Objective-C 2.0 for reasons stated above.
You can't use self.width because it's not a property. self.width = w is shorthand for [self setWidth:w]; which was introduced in Objective-C 2.0. Try adding #property int width; above your method prototypes in the interface file, and at the top of your implementation file under the #implementation line, add #synthesize width;. That should allow you to use self.width, but it would no longer be a private variable.
You could also use #property (readonly) int width; to only generate a 'getter' method for width, but I doubt that's what you want. For more options you can pass to #property, check this documentation page.
Also, like Cliff said, getVar isn't convention in Objective-C. Instead, you just use the name of the variable you want to expose. The get prefix is usually used for when you're returning some form of raw data, as far as I know.
self.width is shorthand for [self width] and since you have not defined a width method it will be illegal. The getters in ObjC do not start with "get" by convention as they would in other languages like Java. Also I've heard from other experts (though I don't understand why) that it's not a good idea to use the property syntax from within the object that owns the proerty. From what I heard it causes some kind of a gotcha with Key Value Coding. In your example if you want to define a custom getter/setter then just reference the value directly without the self qualifier. It probably makes sense to use the getter/setter or dot notation everywhere else for good encapsulation.
self in Objective-C, like this in C++, is a pointer to the current object. So to access a field through self, you would do self->width (just as you would do this->width in C++)
Related
I have experience on C and Python,
I learned the Object-C today,
I want to make sure if my concept is correct ?
I don't know why should I put a statement in a bracket
[pt setX: 8];
Isn't pt setX: 8 meaningful enough ?
If brackets is only for readable, why I got errors in this picture,
I just want to know when should I use the bracket , and when isn't need.
Is pt setX: 8 similar to pt.setX(8) in Python or C-like language?
To create a object,
You have to define .h .m,
In C, you can define and implement both in a .c file , but can not in object-c ?
If you want autorelease the object memory without explicitly free the memory in manual,
Just put your code in the #autoreleasepool block, right ?
#autoreleasepool {
MyPoint* pt = [MyPoint alloc];
// call constructor
pt = [pt init];
[pt print];
[pt getArea];
[pt setX: 8];
[pt setY: 99];
[pt print];
[pt getArea];
}
MyPoint.m
//
// MyPoint.m
// hello_world
//
// Created by poc on 2014/4/27.
// Copyright (c) 2014年 poc. All rights reserved.
//
import "MyPoint.h"
#implementation MyPoint
- (void) print
{
NSLog(#"X =%i and Y= %i", _x, _y);
}
- (void) getArea
{
NSLog(#"Area is %i", _x*_y);
}
- (void) setX:(int)aX
{
_x = aX;
}
- (int) getX
{
return _x;
}
- (void) setY:(int)aY
{
_y = aY;
}
- (int) getY
{
return _y;
}
#end
Is pt setX: 8 not meaningful enough ?
No, it's not. Let's assume situation when you want use result of method invocation as object
pt area intValue // without brackets it's a mess
[[pt area] intValue]; // looks readable now
Is pt setX: 8 similar to pt.setX(8) in Python or C-like language?
Yes, it similar. But you need square brackets
In C, you can define and implement both in a .c file , but can not in object-c ?
Analog of .c file for obj-c is named .m. There you can do the same stuff as you can in .c, importing of .m is really bad practice, it leads you in majority of cases to incorrect linking and, eventually in failure of build. Also it good way to separate private and public interfaces. .h contains public interface to class, you import .h and see only public methods and class variables, while .m contains private methods and variable that you don't want to expose.
If you want autorelease the object memory without explicitly free the memory in manual,
Just put your code in the #autoreleasepool block, right ?
No, it's not. You can't count on autoreleasing of variables you puts there. Autorelease pool created for another purpose. If you want to know why - read this.
I encourage you to use ARC (automatic reference counting), it's enabled by default in latest project templates in Xcode. This way you don't need to worry about memory management, while you correctly use naming convention.
I don't know why should I put a statement in a bracket
That's just the syntax for method calls. Why are parentheses required around arguments in C and Python? Syntax. Other languages don't require parentheses or brackets for method and function calls (e.g. Smalltalk, Ruby and Perl, though parentheses allow you to be more expressive) because they use different syntax. Smalltalk, in particular, is similar to Objective-C method calls, but without the brackets (not coincidentally, since Smalltalk inspired Objective-C).
Is pt setX: 8 similar to pt.setX(8) in Python or C-like language?
Yes. In particular, [pt setX: 8] calls method setX on (or, if you prefer, sends message setX to) object pt, passing 8 as a parameter.
In C, you can define and implement both in a .c file , but can not in object-c ?
Keep in mind that anything declared solely in a compilation unit (a ".c" file) isn't accessible in other compilation units. With Objective-C, you can declare both static variables (as you might in C) and methods in a compilation unit (which have that ".m" extension), but they are effectively private.
If you want autorelease the object memory without explicitly free the memory in manual, [j]ust put your code in the #autoreleasepool block, right ?
An #autoreleasepool block isn't responsible for keeping track of object lifetime; see "Why is autorelease (#autoreleasepool) still needed with ARC?" for what it does. See also "Transitioning to ARC Release Notes" for info on Automatic Reference Counting (ARC) and "Memory management" for info on the older approach (manual reference counting), which is what ARC does under the hood.
This question already has answers here:
declaring array of an object X with unknown size objective c
(2 answers)
Closed 8 years ago.
I have a class named Calculator. This class accepts a bunch of test scores, and will store each of them into an array. This array is called scoreArray.
I want to declare the array like this, but I'm having trouble with the scope:
int scoreArray[numTestScores];
If I put that code into the #implementation, it doesn't know what numTestScores is, because it hasn't been passed to the class yet.
And if I try to do this:
-(id)init:(int)numTestScores_
{
if (self = [super init])
{
int scoreArray[numTestScores_];
}
return self;
}
then the array gets created, but the rest of the class doesn't know what scoreArray is.
How can I make it so that scoreArray is created with length "numTestScores" and has the same scope as if I had put it in the implementation block?
Using a native C array is an unnecessary pain. I'd rather use a NSMutableArray, declaring it as a property.
#property (nonatomic, copy) NSMutableArray *scores;
NSMutableArray automatically manages its memory, so you don't need to declare its size in advance.
Just initialize it as
_scores = [NSMutableArray array];
and then add values to it
[self.scores addObject:#(aResult)]; //assuming that aResult is an integer expression
#(...) wraps the value in a NSNumber since NSArray can only hold objects.
To retrieve a score, you can do
int score = [self.scores[0] intValue];
VLAs (variable-length arrays) only work in contexts where... um... where they make sense. In this case, you will rather want to utilize dynamic memory allocation and an instance variable:
#interface MyClass: NSObject {
int *array;
size_t size;
}
// ... etc ...
- (id)initWithSize:(size_t)n
{
if (self = [super init]) {
size = n;
array = malloc(size * sizeof array[0]);
}
return self;
}
// free the allocated memory upon destruction
- (void)dealloc
{
// ...
free(array);
// ...
[super dealloc];
}
As to why it doesn't really make sense to use a variable-length array as an instance variable: instance variables are part of an object. If you declared a VLA inside an object, then the size of the instance would depend on its initialization. That is not something immediately easy to implement, and it is not the way the Objective-C runtime works. (I'm not saying it's impossible, but it would be very, very impractical.)
All classes have their instance size deduced at compile time (well, mostly... nowadays it's rather the initialization of the runtime system), and it can't be changed later. As a consequence, the size of an object cannot vary from initialization to initialization.
On the assumption that you're writing a properly contained object oriented class, the implementation of your set of scores is not important to the outside world. If that is indeed the case, don't create an int array, create an NSMutableArray instead (and if you want to pre-fill numTestScores_ entries to make things easier later, do that, but there shouldn't be a need for it really).
If you must have an array, you will have to allocate it dynamically by declaring scoreArray to be an int * and using malloc. Be careful here though -- you will have to create a dealloc method in your class to free() the array if it has been created.
I have a Rectangle class which has properties width and height. It also has an instance property/object called origin (-(XYPoint *) origin ). Below is the code for my designated initializer in which I pass the XYPoint object as an argument. Is there a way (or is it okay) if I take the properties of the XYPoint class as arguments in this method and then initialize the XYPoint object as well as allocate memory for it inside the method? Otherwise I have to create an XYPoint object in my main program and pass it as an argument which is a lot more code to type.
-(id) initWithWidth:(int)w andHeight:(int)h andOrigin:(XYPoint *)o
{
self = [super init];
if (self) {
[self setWidth: w andHeight: h];
self.origin = o;
}
return self;
}
P.S.- I am new to programming and Objective C so pardon me if I have stated something technically wrong in my question. Thanks!
Personally--I try to avoid initializers that take parameters. I think it leads to writing lots more code and inflexibility. I use designated initializers for just 2 things:
initializing an object with properties that must not be changed after the object is initialized
initializing an object with properties that are absolutely needed to construct it and cannot be specified later
In general, for Rectangle class, I'd make the use like this:
Rectangle * r = [ [ Rectangle alloc ] init ] ;
r.x = x ;
r.y = y ;
r.origin = o ;
// use r
and not use the designated initializer pattern at all except for the conditions outlined above. (For example, creating immutable Rectangle instances)
Finally, there's probably no need to create a Rectangle class--just use CGRect/NSRect primitive structures.
I'm not sure how much use this question is but it seems interesting to me...
I thought that using property/synthesize statements was equivalent to me creating the getter/setter. Therefore
// .h
#property (nonatomic) BOOL on;
// .m
#synthesize on = _on;
// In my mind synthesizes the following methods
// - (BOOL)on;
// - (void)setOn:(BOOL)on;
However if I change the declarations to the following:
v
#property (nonatomic, getter=isOn) BOOL on;
#synthesize on = _on;
// In my mind synthesizes the following
// - (BOOL)isOn;
// - (void)setOn:(BOOL)on;
Then given the above I override the getter so I know when it is called:
- (BOOL)isOn;
{
NSLog(#"I was called");
return _on;
}
Now calling the following on an instance (myClass) results in:
NSLog(#"%d", [myClass isOn]);
//=> 2012-02-09 22:18:04.818 Untitled[1569:707] I was called
//=> 2012-02-09 22:18:04.820 Untitled[1569:707] 1
NSLog(#"%d", myClass.isOn);
//=> 2012-02-09 22:18:24.859 Untitled[1599:707] I was called
//=> 2012-02-09 22:18:24.861 Untitled[1599:707] 1
NSLog(#"%d", myClass.on); // This is the one I didn't expect to work
//=> 2012-02-09 22:18:55.568 Untitled[1629:707] I was called
//=> 2012-02-09 22:18:55.570 Untitled[1629:707] 1
I had always assumed that if I was using a property in this sense it was perfectly valid to use the getter/setter with dot syntax in the form
myClass.isOn;
myClass.on = on;
From another question it was suggested that when using dot syntax I should use the property name like this:
myClass.on // Correct
myClass.isOn // Incorrect
Although this works it seem slightly less logical because I know there is no underlying method - (BOOL)on it is instead mapped to - (BOOL)isOn
My questions are (using the latter example)
Is this a bug or should myClass.on really be silently changed to call - (BOOL)isOn
Semantically speaking I am accessing state not invoking behaviour so is my current use of dot syntax correct? (e.g. myClass.isOn)
Update
Although no one has explicitly said it I have reasoned that using .isOn is bad form because regardless of the fact that under the hood the same method is called, semantically isOn is asking a question, which is more behaviour rather than state.
However I am still unclear on where the "magic" wiring goes on that turns calls to myClass.on into [myClass isOn]
Update 2
After looking around the docs some more I found this section on Declared Properties. Using the following code I can inspect a class' properties:
id MyClass = objc_getClass("MyClass");
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(MyClass, &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
NSLog(#"Name: %s, attributes: %s\n", property_getName(property), property_getAttributes(property));
}
//=> 2012-02-10 07:10:28.333 Untitled[934:707] Name: on, attributes: Tc,GisOn,V_on
So we have the following attributes:
name = on
type = char (Tc)
getter = isOn (GisOn)
variable = _on (V_on)
With all of this information available at runtime it kind of leaves the question is this lookup done at runtime or compile time like some answers suggest?
However I am still unclear on where the "magic" wiring goes on that turns calls to myClass.on into [myClass isOn]
The logic surely goes as follows, when compiling an obj.name in a getting context:
if(there is an accessible #property for name in scope)
{
if(there is a custom getter specified)
compile "[obj customGetter]"
else
compile "[obj name]"
}
else if (there is an an accessible instance method name in scope)
compile "[obj name]"
else
{
compile "[obj name]"
warn obj may not respond to name
}
There are other ways a language/execution environment can handle custom getter names, but given that Obj-C puts the declaration in the header (which is public) the above is a good guess as to where the custom getter logic is performed - when compiling the call site.
From your experiment we can infer that dot syntax is interpreted as follows:
is there a property with this name? If so, does it have a specified getter / setter name? if so, let's call that method.
otherwise, make up an appropriate method name (direct if we're getting, setXX if we're setting) and throw that at the receiver.
You can, for example, try to use .count against an NSArray instance. Before the abomination police kick in your doors, you may have time to see that it works.
To actually answer your question, in my mind dot notation should only be used to access properties, and in that case you should use the property name as declared in the interface. So .on for a UISwitch. I don't know why the getter name isn't given in the synthesize statement instead of the property declaration, it seems to belong in implementation rather than interface to me.
Well concerning dot notation, let me cite Aaron Hillegass (Cocoa Programming for Mac OSX, 3rd. Ed):
"Overall, I think that this is a rather silly addition to the language since we already had a syntax for sending messages."
When you have a member variable on, and your getter for this variable is called isOn then .on and .isOn are two very different kind of things. By using the getter (and probably a setter, too) you will adhere to the "information hiding" promise, whereas by using direct access to the member variables you won't. Cocoa won't enforce those things as it is relying on conventions. It's up to you to decide which way is right for you. Considering convention, you would have to stick to setters and getters - no matter what names you give them, though.
Property declarations are merely shorthand for regular method declarations. E.g.:
#property int color;
#property (getter=isOn) BOOL on;
becomes these method declarations:
- (int)color;
- (void)setColor:(int)value;
- (BOOL)isOn;
- (void)setOn:(BOOL)on;
You can call these methods just like any other method:
[foo color];
[foo isOn];
Likewise, dot notation is merely informal shorthand for calling plain old methods. For example:
x = #"Hello".length;
x = foo.on;
x = foo.isOn;
becomes
x = [#"Hello" length];
x = [foo isOn];
x = [foo isOn];
Note that #"Hello".length works even though NSString does not actually declare a property named "length". By default, foo.bar always expands to [foo bar] unless bar has been declared a property with a custom getter. If bar happens to be the name of a valid method then it will work without error.
Likewise, in your example foo.isOn works even though you don't actually declare a property named "isOn". Rather "isOn" is the name of a method that just happens to be the getter method for your "on" property.
So, while foo.isOn may work, it's considered bad form because isOn is not actually the name of the property.
What you cannot do is this:
x = [foo on]; // Error
because you never declare an on method.
I'm a new iPhone/Objective-C developer and as I'm going through different tutorials and open source code, I am having a bit of a problem understanding when to use the square brackets "[ ]" and when to use the period " . " for accessing properties/methods of an object.
For example, this code:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
UIColor *backgroundColor = nil;
if (selected){
backgroundColor = [UIColor clearColor];
} else {
backgroundColor = [UIColor whiteColor];
}
self.todoTextLabel.backgroundColor = backgroundColor;
self.todoTextLabel.highlighted = selected;
self.todoTextLabel.opaque = !selected;
self.todoPriorityLabel.backgroundColor = backgroundColor;
self.todoPriorityLabel.highlighted = selected;
self.todoPriorityLabel.opaque = !selected;
}
Why does [UIColor clearColor] get brackets, but todoTextLabel.backgroundColor get the period?
Could someone explain this easily for me?
The convention I have seen in new code is to use the dot for properties, and always use square brackets for messages/selectors (what you call methods). The dot was introduced in Objective-C 2.0, so the disagreement of information you find online is not entirely unexpected.
It's also entirely possible to use square brackets for everything, still (and I do):
foo = [myObject backgroundColor];
[myObject setBackgroundColor:foo];
is equivalent to
foo = myObject.backgroundColor;
myObject.backgroundColor = foo;
To reiterate, you should not be using the dot for messages, only properties.
To answer your specific question, [UIColor clearColor] belongs in brackets because it is not a property; it's actually a class message to UIColor (+(UIColor)clearColor).
You sound like you come from a Java world, so this might be helpful:
MyObject *foo = [[MyObject alloc] initWithAwesome:YES]; /* MyObject foo = new MyObject(TRUE); */
[foo doSomethingWithNumber:5 andString:"five"]; /* foo.doSomething(5, "five"); */
MyColor *bar = foo.faceColor; /* MyColor bar = foo.faceColor; */
MyColor *baz = [foo faceColor]; /* MyColor baz = foo.faceColor; */
foo.backColor = bar; /* foo.backColor = bar; */
[foo setUndersideColor:baz]; /* foo.undersideColor = baz; */
The "setXXX" and "XXX" messages come from synthesized dynamic properties, and are an Objective-C idiom. The "dot" is simply a shorthand for calling those methods, and is roughly equivalent.
EDIT: Now that I've got some upvotes, time to make some of you reconsider >:)
I never use dots, and neither should you.
I use dot notation for properties because,
for ( Person *person in group.people){ ... }
is a little easier to read than
for ( Person *person in [group people]){ ... }
in the second case readability is interupted by putting your brain into message sending mode, whereas in the first case it is clear you are accessing the people property of the group object.
I will also use it when modifying a collection, for instance:
[group.people addObject:anotherPerson];
is a bit more readable than
[[group people] addObject:anotherPerson];
The emphasis in this case should be in the action of adding an object to the array instead of chaining two messages.
Big Nerd Ranch has some thoughts on the dot notation that are worth reading.
There's also a rebuttal.
By (strong) convention, property accessors are written as methods named after the instance variable for the getter, and the (capitalised) instance variable name prefixed with "set" for the setter (so for instance variable foo you'd have foo and setFoo).
As others have pointed out, as of Objective-C 2.0, if you write object.foo, it will map onto method call [object foo] if getting or [object setFoo: arg] for setting. You can use either form, and some people continue to prefer the full method syntax even when using Objective-C 2.0 exclusively.
A separate, but related, addition to Objective-C 2.0 are the #property/#synthesize/#dynamic keywords for generating the getters and setters. You can mix and match these with dot notation - one does not require the other.
Yep, I just started learning this too:
Unlike other languages, syntax to invoke a method on an object is not objName.someMethod();
It's [objName someMethod]
The dot operator is used to either get or set the value of a property in a class. It's a short way of doing something.
The dot operator, as I have seen it, is always used on an instance of an object whereas the [...] can be used on either an instance of an object or statically (using the class name).
todoTextLabel can use the [] also but using the dot operator is just shorter hand...otherwise you would have to provide parameters, etc, and that's just longer notation.
Hope this helped.