Which Object Oriented Programming concept is displayed by destructors? For example, overloading shows polymorphism. Please explain the reason for your answer. I could not find this anywhere on the web..
Most of the key OOP concepts are shown by destructors. If we consider those concepts as including Inheritance, Object, Class, Encapsulation, Method, Message Passing, Polymorphism, Abstraction, Composition, Delegation and Open recursion. Then we can show all of them being at play in destructors generally.
Now, generally "destructor" means a method that is defined in a class that is automatically invoked when an object is destroyed*. That obviously covers method, object and class.
Destructors encapsulate clean-up logic. Consider a structure that can point to another structure:
struct SomeStruct
{
SomeStruct* Next;
}
If the above was written in a language that didn't support object-oriented design by letting us define a method on SomeStruct itself, and that deletes heap objects with a global delete() method, then to clean up all the memory used by a SomeStruct we'd need to do something like:
CleanUpSomeStruct(SomeStruct* toDelete)
{
while(toDelete != null)
{
SomeStruct* deleteNext = someStruct->Next;
delete(toDelete);
toDelete = deleteNext;
}
}
Notably:
We have to do the work to clean up SomeStruct outside of SomeStruct.
There's nothing to prevent this being duplicated elsewhere. Perhaps incorrectly.
We have to be able to access Next directly, increasing the number of places we might do something unwise with it.
If we have cases where we shouldn't delete Next, then while that knowledge could be stored in SomeStruct (perhaps an ownsNext field), the logic of acting on that knowledge is external to SomeStruct.
If we have destructors then:
struct SomeStruct
{
SomeStruct* Next;
~SomeStruct()
{
if(Next != null) delete(Next);
}
}
In contrast to the above:
The work to clean up SomeStruct is in SomeStruct, close to other SomeStruct-related code.
It's possible to have a concept of access-control, which can prevent this being duplicated elsewhere.
Likewise, access-control can stop other cases of accessing Next directly, decreasing the number of places we might do something unwise with it.
If we have cases where we shouldn't delete Next, then that logic can be stored in one place internal to SomeStruct.
On the flip side, since encapsulation means that we may not be able to access Next encapsulation means that we have to have destructors to be able to clean up objects (or give the method an explicit "Clean Yourself Up" method, but having to remember to call it every time, and know if it even exists in a given case, and what it's called is a drag). Obviously this example wouldn't matter if we had automatic garbage collection, but in those cases we would similarly need to have destructors of some sort if encapsulation blocked outside code from necessary clean-up task.
Likewise, if we have inheritance, we need to have inheritable destructors that can pass the clean-up task up the line either implicitly or explicitly:
struct SomeOtherStruct : SomeStruct
{
SomeStruct* Prev;
~SomeOtherStruct()
{
if(Prev != null) delete(Prev);
base.~SomeStruct(); // Possibly this would be implicit in that
// the language would automatically make a
// call to a destructor finish with a call
// to any base destructors.
}
}
This also requires that destructors be abstract in the general sense of being part of the abstract model of what an object is (it may not have anything to do with an abstract keyword used to enforce abstraction in other contexts). They must be polymorphic so that delete(Prev) calls the most derived destructor in the object pointed to by Prev whether it is ~SomeStruct(), ~SomeOtherStruct() or the destructor of yet another derived type, so Message Passing/Dynamic Dispatch is used to find the correct implementation of the abstract/virtual destructor. (A language may enforce this, or may allow non-virtual destructors as an optimisation).
Finally destructors interact with encapsulation and open recursion in that they will have to (perhaps implicitly) call the destructors of objects they are composed of, and perhaps call into methods on themselves to do this.
*"when an object is destroyed" is a plainer concept for languages/frameworks using deterministic deletion of objects than those with non-deterministic garbage collection. Generally in the later case "destructor" refers to a method that runs when that non-deterministic collection finally happens (assuming it ever does) but if they have a separate "disposal" method that can be deterministic then it may serve some of the rôles that deterministic destructors serve. In particular while deterministic destructors can be useful in providing for the RAII technique, non-deterministic destructors do not and any use of RAII-like approaches would have to be part of a deterministic disposal.
The practice of freeing up your program resources exists before OOP came to life. Even in old school C, without any objects, you have to free your memory accordingly or you get memory leaks, resource locks or other not nice consequences.
The concept is Garbage Collection. In oop you can relate it with freeing up space that was previously allocated to any object which is no longer needed or deleted.
To quote the wikipedia
In object-oriented programming, a destructor (sometimes shortened to
dtor) is a method which is automatically invoked when the object is
destroyed.
It's role is useful in cleanup, as in freeing up memory space that is longer used by your program anymore. Since most of the modern programming langauge has automatic Garbage Collection, the explicit call to the destructor is no longer needed.
Read about GC and Finalizer for more info.
Hope it helps.
Destructors implement what we know as "Resource Acquisition Is Initialization"
Related
In Android, I could safely access and modify primitive types from different threads. I used this to share data between my OpenGL draw loop and user settings that were modified in the main thread Android UI. By storing each setting in a primitive type and making each independent of the others' values, it was thread-safe to modify all these variables without using locks or the synchronize keyword.
Is this also true in Objective-C? I read that placing atomic on a variable essentially causes the synthesized getter and setter to use locks, similar to using synchronized methods in Java. And I've read that the reason for this is so an object does not get partially modified while it's being read by another thread.
But are primitive types safe from being partially modified, as they are in Java? If that is the case, it seems like I could use my same old paradigm from Java for sharing data between threads. But then the atomic keyword would be pointless for a primitive, correct?
I also read that a more robust and faster solution than using atomic variables is to copy objects before using them if they are accessed from multiple threads. But I'm not sure how that could be accomplished. Couldn't a nonatomic object get modified while it's in the process of being copied, thereby corrupting the copy?
Primitive types aren't guaranteed to be safe from being partially modified because modifications to primitive types aren't guaranteed to be atomic in C and Objective-C inherits from there. C's only guarantees concern sequence points and there's no requirement that the processing between two sequence points be atomic — a rule of thumb is that each full expression is a sequence point.
In practice, modifying primitives is often a two-step process; the modification is made in a register and then written out to memory. It's very unlikely that the write itself will not be atomic but there's also no guarantee of when it will occur versus the modification. Even with the volatile qualification, the only guarantees provided are in terms of sequence points.
Apple exposes some C functions for atomic actions via OSAtomic.h that map directly to the specialised atomic instructions that CPUs offer for the implementation of concurrency mechanisms. It's possible you could use one of those more directly than via a heavy-handed mutex.
Common patterns in Objective-C are:
immutable objects and functional transformations — there are memory management reasons as well but that's partly why NSString, NSArray, etc, are specifically distinct from NSMutableString, NSMutableArray, etc;
serial dispatch queues, which can be combined with copy-modify-replace by copying on the queue, going off somewhere else to modify, then jumping back onto the queue to replace;
such #synchronizeds, NSConditionLocks or other explicit synchronisation mechanisms as are appropriate.
The main thread itself is a serial dispatch queue, which is why you can ignore the issue of concurrency entirely if you restrict yourself to it.
Atomic synthesized #properties are immune to concurrent partial updates. The accessor methods will use a lock if necessary on that architecture.
In general, primitive types in C are not necessarily safe with respect to concurrent partial updates.
I don't believe you can partially modify a primitive type, that's part of what makes them primitive. You either modify it or you don't. In that sense, I would say that they are thread safe.
You are correct when you say that the atomic keyword would be pointless for a primitive type.
Someone already took a stab at this here:
Objective-c properties for primitive types
In Objective-C, when I want to call a subroutine, I send a message to an object, like:
[self mySubroutine:myParameter];
There is a (negligible?) performance penalty, so I could just use a C-style function call:
mySubroutine(myParameter);
The implementation of the latter would then reside outside the class’s #implementation context.
Is this a no-no? Is it common? Is there a best-practice on this?
Note that those are not necessarily equivalent. Since -mySubroutine is an instance method, it probably needs to access a given instance. In that case, your mySubroutine() function should have another parameter for the instance, too.
In general, use a method. If you’re worried about performance,1 you can always get an IMP to the method and use it as a function instead of the standard Objective-C message dispatch infrastructure.
That said, some disadvantages of using functions:
They cannot be overridden by subclasses;
There’s no introspection (when using the runtime to obtain a list of methods declared by an Objective-C class, functions aren’t enumerated);
They cannot be used as accessors/mutators of declared properties;
They aren’t visible to Key-Value Coding;
They cannot be directly used for Objective-C message forwarding;
They cannot be directly used in the various cases where a Cocoa API expects a selector (e.g. when using NSTimer).
Some advantages of using functions:
They cannot be overridden by subclasses (if you want to prevent this);
There’s no introspection (if you want to prevent this);
They can be inlined;
They can have file scope (static), preventing code from other files from accessing them.
1When you’ve determined that the message dispatch infrastructure is actually a bottleneck. This does happen; for instance, some Apple audio examples do not use Objective-C for audio processing.
Edit: Based on OP’s comment, another advantage of functions is that they aren’t necessarily related to a class. If the computation of an approximate value for the sine of an angle doesn’t depend on an Objective-C instance, there’s no need to make it a method — a function is a better fit.
It might be worth using where you have static utility functions, such as in a maths library.
In general though, if you need methods that act on the state of an object, the C approach won't be much use, as you won't have implicit access to self, unless you explicitly pass it as a parameter.
You may also run into namespace issues. With the Objective-C different classes can share method names, with the c approach all your functions will need different signatures.
Personally I would always use objective-c methods, the performance difference will be negligible.
I was wondering if there are any memory/performance drawbacks, or just drawbacks in general, with using Class Methods like:
+ (void)myClassMethod:(NSString *)param {
// much to be done...
}
or
+ (NSArray*)myClassMethod:(NSString *)param {
// much to be done...
return [NSArray autorelease];
}
It is convenient placing a lot of functionality in Class Methods, especially in an environment where I have to deal with memory management(iPhone), but there is usually a catch when something is convenient?
An example could be a thought up Web Service that consisted of a lot of classes with very simple functionality. i.e.
TomorrowsXMLResults;
TodaysXMLResults;
YesterdaysXMLResults;
MondaysXMLResults;
TuesdaysXMLResults;
.
.
.
n
I collect a ton of these in my Web Service Class and just instantiate the web service class and let methods on this class call Class Methods on the 'Results' Classes. The classes
are simple but they handle large amount of Xml, instantiate lots of objects etc.
I guess I am asking if Class Methods lives or are treated different on the stack and in memory than messages to instantiated objects?
Or are they just instantiated and pulled down again behind the scenes and thus, just a way of saving a few lines of code?
Short answer: no downside - use as expected
Long answer: Classes in objective-c are actually objects, that you can use like anything else (check the return type of -[NSObject class] -- a pointer to an obj-c object). When you call [yourclass alloc], you're actually sending a message to yourclass, which is an object describing the class to the runtime. (the method itself is a bunch of wrappers around malloc(), so there's not exactly any magic involved.) As far as how these objects are handled, ALL objects in objc, including classes, are allocated in the heap, so the stack plays no part. EDIT: Just to be clear, there is no difference in using a class method as opposed to an instance method, except that with a class method you do not need to have an instance of the class.
for further reading on how these class objects are implemented, I recommend http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html
In my experience, class methods, or in my definition static functions, serve specific purposes. One of them CAN be performance, but only if they are small and not dealing with a lot of data. (i.e. NSString stringWithString). If you are dealing with a lot of data, your performance hit, as you are probably aware, is in dealing with the data, not the instantiation of an object. Stick with focusing on the dealing with the time consuming task as opposed to the overhead of creating objects to handle the task.
SPECIFIC ANSWER: Class Methods are loaded at load time, and are always available to your application, the code overhead for loading them via a class instantiation is minimal compared to the large amount of work you describe. (They will most likely be cached anyway)
As is common knowledge, calls to alloc/copy/retain in Objective-C imply ownership and need to be balanced by a call to autorelease/release. How do you succinctly describe where this should happen? The word "succinct" is key. I can usually use intuition to guide me, but would like an explicit principle in case intuition fails and that can be use in discussions.
Properties simplify the matter (the rule is auto-/release happens in -dealloc and setters), but sometimes properties aren't a viable option (e.g. not everyone uses ObjC 2.0).
Sometimes the release should be in the same block. Other times the alloc/copy/retain happens in one method, which has a corresponding method where the release should occur (e.g. -init and -dealloc). It's this pairing of methods (where a method may be paired with itself) that seems to be key, but how can that be put into words? Also, what cases does the method-pairing notion miss? It doesn't seem to cover where you release properties, as setters are self-paired and -dealloc releases objects that aren't alloc/copy/retained in -init.
It feels like the object model is involved with my difficulty. There doesn't seem to be an element of the model that I can attach retain/release pairing to. Methods transform objects from valid state to valid state and send messages to other objects. The only natural pairings I see are object creation/destruction and method enter/exit.
Background:
This question was inspired by: "NSMutableDictionary does not get added into NSMutableArray". The asker of that question was releasing objects, but in such a way that might cause memory leaks. The alloc/copy/retain calls were generally balanced by releases, but in such a way that could cause memory leaks. The class was a delegate; some members were created in a delegate method (-parser:didStartElement:...) and released in -dealloc rather than in the corresponding (-parser:didEndElement:...) method. In this instance, properties seemed a good solution, but the question still remained of how to handle releasing when properties weren't involved.
Properties simplify the matter (the rule is auto-/release happens in -dealloc and setters), but sometimes properties aren't a viable option (e.g. not everyone uses ObjC 2.0).
This is a misunderstanding of the history of properties. While properties are new, accessors have always been a key part of ObjC. Properties just made it easier to write accessors. If you always use accessors, and you should, than most of these questions go away.
Before we had properties, we used Xcode's built-in accessor-writer (in the Script>Code menu), or with useful tools like Accessorizer to simplify the job (Accessorizer still simplifies property code). Or we just typed a lot of getters and setters by hand.
The question isn't where it should happen, it's when.
Release or autorelease an object if you have created it with +alloc, +new or -copy, or if you have sent it a -retain message.
Send -release when you don't care if the object continues to exist. Send -autorelease if you want to return it from the method you're in, but you don't care what happens to it after that.
I wouldn't say that dealloc is where you would call autorelease. And unless your object, whatever it may be, is linked to the life of a class, it doesn't necessarily need to be kept around for a retain in dealloc.
Here are my rules of thumb. You may do things in other ways.
I use release if the life of the
object I am using is limited to the
routine I am in now. Thus the object
gets created and released in that
routine. This is also the preferred
way if I am creating a lot of objects
in a routine, such as in a loop, and
I might want to release each object
before the next one is created in the
loop.
If the object I created in a method
needs to be passed back to the
caller, but I assume that the use of
the object will be transient and
limited to this run of the runloop, I
use autorelease. Here, I am trying to mimic many of Apple's convenience routines. (Want a quick string to use for a short period? Here you go, don't worry about owning it and it will get disposed appropriately.)
If I believe the object is to be kept
on a semi-permanent basis (like
longer than this run of the runloop),
I use create/new/copy in my method
name so the caller knows that they
are the owner of the object and will
have to release the object.
Any objects that are created by a
class and kept as a property with
retain (whether through the property
declaration or not), I release those
in dealloc (or in viewDidUnload as
appropriate).
Try not to let all this memory management overwhelm you. It is a lot easier than it sounds, and looking at a bunch of Apple's samples, and writing your own (and suffering bugs) will make you understand it better.
I'm wondering what are the recommended ways to handle situations where, in memory managed code, object didn't belong to any particular owner, i.e. objects released themselves. One such example could be a subclass of NSWindowController, which configures, displays and manages input and output of a single window. The controller object displays a window and releases itself later at some point (usually when the window or sheet it manages is closed). AppKit provides couple examples as well: NSAnimation retains itself in startAnimation and releases itself when the animation is done. Another example is NSWindow, which can be configured to release itself when closed.
When implementing these "self-owned" objects myself, I see at least three different GC-safe patterns, but all of them have some drawbacks.
a). Using CFRetain/CFRelease.
Self-owned object calls CFRetain on self before it starts its operation (e.g. in the window controller example before the window is displayed). It then calls CFRelease() on self when it's done (e.g. in the window controller example after the window is closed).
Pros: User of the object doesn't have to worry about memory management.
Cons: A bit ugly, since requires use of memory management functions, although we're using GC in pure ObjC code. If CFRelease() isn't called, leak may be hard to locate.
b). Avoiding self-ownership idiom with static data structure.
Object adds itself into a data structure (e.g. a static mutable array) before it starts its operation and removes itself from there when it's done.
Pros: User of the object doesn't have to worry about memory management. No calls to memory management functions. Objects have explicit owner. Potential leaks are easy to locate.
Cons: Locking is needed if objects may be created from different threads. Extra data structure.
c). Avoiding self-ownership idiom by requiring the user of object to save a reference to the object (e.g. into an ivar).
Pros: No calls to memory management functions. Objects have explicit owner.
Cons: User of the object has to keep a reference even if it doesn't need the object anymore. Extra ivars.
What pattern would you use to handle these cases?
For a), the more idiomatic alternative to CFRetain(foo)/CFRelease(foo) is [[NSGarbageCollector defaultCollector] disableCollectorForPointer:foo]/[[NSGarbageCollector defaultCollector] enableCollectorForPointer:foo].
Apple's recommendation is (c), but I like the sound of (b). A static data structure allows you to hide the GC details from the API user while avoiding dipping into the CFRetain/CFRelease level. As you state, it also makes debugging and unit testing easier; if an object is still referenced by the static data structure after it's finished its task, you know there's a bug.