I'm studying up on archiving data, and I realize the standard collection classes provide easy archival, however I want to archive an NSMutableArray. So I read that since NSMutableArray "is a" NSArray because it is a subclass, then this is fine.
But that idea stumps me, and I realize this is a basic concept of Objective-C so I want to make sure I get it right.
Suppose you have a class "automobile" with a subclass "jeep." Now based on the above, you can say this:
automobileInstance=jeepInstance;
...because a jeep is a subclass of automobile.
But this seems backwards to me. I would think you should instead say that a subclass instance can be equal to its superclass instance:
jeep = auto
Because after all a jeep "is a" automobile, but not all automobiles are jeeps.
So why then can you do this:
NSArray*newArray=nsmutableArrayInstance;
It's the same idea as saying:
automobile=jeep; in my example.
Your subclass might have added many new instance variables, for example, but if you set it equal to a superclass, those iVars are "lost" or at least the super class doesn't recognize them, so it isn't truly capturing the object, it would seem.
Going the other way, saying the sublass instance = superclass instance makes sense, since everything in the superclass is in the subclass; you just don't get values for the extra iVars that are in the subclass but not in the superclass, they might be set to default zero, but at least they exist.
Think of it this way: all jeeps are automobiles. Not all automobiles are jeeps. So you can say:
Automobile a = jeepInstance; // A jeep is always an automobile
But not:
Jeep j = autoInstance; // fails - autoInstance might be a Mazda, instead.
A superclass pointer can point to an object allocated from the subclass, since the class members of the superclass are always present in the subclass.
autoMobilePointer = jeepObject; // works
This isn't true the other way around, since the subclass has members that are not present in the superclass.
jeepPointer = autoMobileObject; // doesn't work
I think the problem here is that you're confusing assignment and equality, and maybe classes and objects, too. Remember that = means assignment, whereas == and -isEqual are tests for equality. If B is a subclass of A, then every B is an A, just as every Jeep is an automobile, and every human is a mammal.
But when you say:
automobile = jeep;
what you're doing is assigning the value of jeep to the variable automobile. You're not saying that every automobile in the world is a Jeep, you're saying that the specific variable automobile refers to a specific instance of Jeep. It's exactly as if I asked you:
What car do you drive?
In my head, I'm expecting you to reply with information about some car. You could say that the memory location in my head that I've reserved for your answer has type Automobile*, since it could refer to any car. You reply:
I drive that red Jeep parked near the tree.
It might help to choose more descriptive names for your variables. Use something specific, like:
Automobile *theCarThatAndrewxDrives = jeep;
This makes it obvious that we're talking about one specific car, not all cars.
Related
Let me consider following piece of code:
Person *peter = [people chooseRandomPerson];
where "people" is class instance, which was already initialised, and "chooseRandomPerson" is method which returns object of "Person" type. I wonder if it's the same as following:
Person *peter = [[Person alloc] init];
peter = [people chooseRandomPerson];
If not, what is the difference. If not, can I use such a substitution anytime? I am sorry, if the question is elementary, but I wasn't able to find an answer.
The second creates an object, puts it into the variable peter, and then immediately discards it* to store the return value of chooseRandomPerson.
The variable peter is a place to put a thing; the object is the thing you get back from the alloc/init or the chooseRandomPerson. You don't need to create a thing in order to have a place to put it; the declaration Person *peter; creates the place -- the variable -- by itself.
*If you weren't using ARC, this would be a leak, but if you're asking this you'd better be using ARC.
The answer by Josh Caswell is correct. But your question is not entirely clear.
In your question, you never define what is "people". You say "class instance" by which you presumably meant "object". But an object/instance of what class? Using the plural word "people" suggests a collection of objects. You should clarify this in your question.
Object Creating Sibling Objects
If you are asking "Can an object return a new instance of its own class?", the answer is "Yes". In your example, "peter" a Person object can produce a new Person object, "Sally".
However, an object creating sibling objects (new objects of the same class) is somewhat unusual in my experience. More common would be a using the Factory design pattern to produce instances.
There is one common use of an object creating sibling objects: Immutable objects. Instead of changing one field of data in a DateTime object, an entirely new object is created with most of its data based on the original.
Quick question: The difference between (ReturnClass *)methodName... and (ReturnClass)methodName... in Objective-C?
I know (ReturnType *)methodName... returns an instance of ReturnClass as opposed to (ReturnClass)methodName just returning what?
Thank you.
if your ReturnClass is an object (which is most likely) then you can't use it without *. You'll get a compilation error. Otherwise *is a pointer to instance (primitive type or struct), and absence of * is instance itself
EDIT: Brilliant explanation on pointers from Joe:
Think of the instance as your house and the pointer as your address. Your house is a large object, so instead of making copies of your house and passing it to your friends when you have a party you give them your address so they can get to your house. Now if you had a small object, like a flyer, it would be easy to just make copies and pass out rather than give everyone instructions to get to that piece of paper. Think of the large object (house) as an Objective-C class or struct full of info, and the small object (flyer) as a primitive like int, BOOL, double etc
Let us say that application has a concept of cars in it. A car is an instance of Car. There are a small number of possible cars and most, but not all of the data about a car is known at design time. Each kind of car is a singleton; there is at most one of each kind of Car per app.*
Since they are singletons, and since they are named, that suggests some sugar. The most important piece of sugar is this: when I import "Car.h", into a file, I want the symbols "MAFerrari", "MAMercedes", and "MAMclauren" to start showing up in my autocomplete where ever code completion thinks I am trying to provide an instance of a Car*.
My next greedy desire is that I want to be able to send instance methods to my MAFerrari literal, e.g. [MAFerrari topSpeed] means "get the singleton instance of Car that corresponds to the Ferrari and send topSpeed to it", but I acknowledge the utter triviality of this. Even pragmatists should know what their Utopia looks like.
Finally, if possible, I want clean way to declare the constant properties of the three cars as literal data at the top of my Car.m file.
Now, again, I don't actually expect all of that to be possible in Objective C. I just want to know how close we can get to that all that.
The closest idea I've had is to subclass Car for each type of car and provide a +sharedInstance method for each one. sharedInstance can implement the singleton pattern: if it's initialized, return it, otherwise initialize it, store it (where? it should be private to the Car class hierarchy), then return it. Each subclass can implement its own initializer which contains the defaults for that subclass.
Here's what I don't like about this:
I think I have to import all the header files whenever I work with these subclasses. This absolutely sucks. Is there another way?
I have to create .m/.h file pair for every one of these subclasses. That seems like a lot of boilerplate, since they have no unique behavior.
[[MAFerrari sharedInstance] topSpeed] isn't quite as good as [MAFerrari topSpeed], but I acknowledge that this is trivial.
Anyway, how would you do it?
*In reality, it's not cars, but in-app purchase assets, for the curious.
It sounds like what you want is just a global variable. You can create a global variable named whatever you want (say, MAFerrari) and stick whatever you want in it — whether the contents of the variables are instances of multiple singleton classes or multiple instances of the same class doesn't really matter from the point of view of having global names to refer to the objects.
Easy-peasy.
Note that these aren't singletons; they're just long-lived instances of a class stored in global variables.
// Bolt.h
#import <Foundation/Foundation.h>
#interface Bolt : NSObject
// Properties
- (instancetype)initWithLength:(NSUInteger)length
diameter:(NSUInteger)diam
thread:(NSUInteger)thread
grade:(NSUInteger)grade;
// etc.
#end
extern Bolt * twentyFiveByTwelveCoarseThreadGradeEightBolt;
extern Bolt * fiftyByTenFineThreadGradeFiveBolt;
//
// Bolt.m
#import "Bolt.h"
Bolt * twentyFiveByTwelveCoarseThreadClassEightBolt;
Bolt * fiftyByTenFineThreadGradeFiveBolt;
// This will be run before main() but after classes are loaded
__attribute__((constructor))
static void initialize_global_Bolts(void)
{
twentyFiveByTwelveCoarseThreadClassEightBolt = [[Bolt alloc] initWithLength:25
diameter:12
thread:175
grade:8];
fiftyByTenFineThreadGradeFiveBolt = [[Bolt alloc] initWithLength:50
diameter:10
thread:1
grade:5];
}
#implementation Bolt
- (instancetype)initWithLength:(NSUInteger)length
diameter:(NSUInteger)diam
thread:(NSUInteger)thread
grade:(NSUInteger)grade
{
// Do initialization
}
#end
Now you can do things like [fiftyByTenFineThreadGradeFiveBolt maximumTorque]; wherever Bolt.h is imported.
You can't put dictionary or other literals at top level, because they resolve into method calls, which can't be used outside of other methods.
Novice here attempting to understand inheritance. If I initialize a new object with several properties and I want other classes to help assign values to those properties, do I need to create instances of those other classes? Visualized:
-(ObjA *)init{
self = [super init];
self.property1 = [method from Class A];
self.property2 = [method from Class B];
self.property3 = [method from Class C]; etc...
return self;
}
In other words, assuming Class A, B, and C need to know what Object A is, would I need to make those class methods instance methods and initialize each object? Is there another way to go about this? Thank you in advance for your help.
In other words, assuming Class A, B, and C need to know what Object A
is
NO.
You can simply call a method from ClassA/B/C etc. But the return type must match with respective property.
Let, the property1 is for kind NSString then your ClassA method must be
-(NSString *)methodClassA{
...
return someStringValue;
}
Then you need to use:
ClassA *objClassA=[ClassA new];
self.property1=[objClassA methodClassA];
Or you can go with class method by this:
+(NSString *)methodClassA{
...
return someStringValue;
}
And using it as:
self.property1=[ClassA methodClassA];
assuming Class A, B, and C need to know what Object A is
The initialization code of an object should be self contained, unless it is using functionality owned by a different object, in which case the object acts as a client of that functionality. That is, objectA acts as client of A,B,C (as seen in your code).
But this doesn't imply that A,B,C need to know (have a dependency on) objectA. By doing that, you are saying that they don't have a reason to exist on their own.
In general,
Every class or method should have one encapsulated purpose. This makes it easy to understand, change, and test in isolation. It's a common pattern to create classes whose sole purpose is to encapsulate information to create a different class, but to split that in three different classes is beyond weird (as in, I can't imagine an example of that).
An object shouldn't be allowed to exist in an unusable state, nor should it require non essential information when it is created. Does objectA require those properties to function? if it does, your code is right, if it doesn't, the initializer is providing too much information and making it less reusable.
Try to rethink your doubt with a real (instead abstract) example. You may end up making sense of it yourself.
I have an object that has several properties. If I have a pointer to one of those properties, is it possible to get a pointer to the class instance to which that ivar belongs?
for example: foo.bar, where I know the address of bar, can the address of foo be found?
This seems related to: run time references but I didn't see any references that were quite what I'm looking for.
Thanks for your help!
First, you need to adjust your terminology a bit. You cannot have a pointer to a property, because a property is an interface to an object, specifying the format of the getter and setter methods.
If you had a pointer to the getter, a method (IMP) at best you could get back would be a pointer to the class, certainly you could not get back to an instance.
If you had a pointer to an ivar, I don't believe there is any way to get back to the containing object instance. If you had an array of all posible foos, it might be possible to ask each of them for a list of ivars, and get the address of each ivar and eventuallty find the instance in question that way.
The best solution is for bar to contain a parent reference to foo, so that foo.bar.foo will give you the answer you want. But it depends on what exactly you are trying to do. The normal Cocoa way for a lot of these things is to pass foo as well, as is done for many delegates. For example:
[obj foo:foo doSomethingWithBar:foo.bar];
Unless the object has a pointer back to it's "parent" or you explicitly track it yourself, I don't believe there's a way to resolve that. You'd really have to trace through memory to find what basically amounts to "who points to me". It's essentially the same problem as finding the previous node in a singly-linked list — you have to start from the beginning and stop when you reach the node that points to the node of interest.
The problem with trying to track down foo from the address to bar is that foo.bar is a pointer that contains the address of an object, and only foo calls it "bar". For simplicity's sake, imagine that foo is at address 0x1000, and foo.bar is at 0x1008 and points to another object at 0x2000. Now, if you have the address 0x2000, there's no easy way to know that 0x1008 points to it.
It's even more complicated if you imagine that N other addresses might also point to 0x2000, so even if you did scan memory, you wouldn't know whether the pointer belonged to an object, struct, local variable, or even was just a random pattern that happened to match the address you're looking for.
You could do it if you have a pointer to the instance variable itself, rather than the contents of the instance variable.
Foo * reference = [[Foo alloc] init];
Foo * foo == [[Foo alloc] init];
int * barptr = &(foo->bar);
Foo * baz = (Foo *)((char *)barptr - ((char *)(&(reference->baz)) - (char *)reference));