Redefining instance variables of a Smalltalk class - smalltalk

I've never used Smalltalk, but I've read a lot about it and it has always intrigued me. I've seen the cool demos where a program is running and simply by changing the methods of the classes the program's objects are using alters the running program's behavior. It's clearly powerful stuff and I understand how that can work the way it does. What I can't seem to nail down for certain is what happens to the existing instances of a class when you want to add, remove, or rename instance variables of that class.
I can't imagine how one can alter the instance variables that all the classes are using in a running program and still expect the existing instances of that class to function correctly afterward. Perhaps I'm adding a new instance variable that I need to have initialized and where previously existing methods have been altered to depend on this variable. Couldn't I end up with a horrible malfunction of any running code that has live instances of that class? Or what if the meaning of an instance variable has changed and I now expect a different kind of object to be stored there than was previously? Is there some kind of "upgrade" mechanism? Or is the usual practice to just let the previous instances crash and burn? Or is this simply a case of "we don't do that sort of thing on running programs and expect them to survive?"
The only reasonably clean approach I can think of is that when you alter the instance variable definitions perhaps it actually creates an entirely new class and the old instances, prior to the change, continue to function just fine with the old class definition (which is now inaccessible by name since the name was redefined to the new class definition). Perhaps that is the most logical explanation - but since I haven't found anything that directly explains this process, I figured I'd ask here and see what kind of fun information that got me. :)

According to this paper, it is like you said:
It also automatically manages class redefinition, guaranteeing system consistency in terms of object structures and preventing name conflicts, especially instance variable name conflicts. When a class definition changes, existing instances must be structurally modified in order to match the definition of their new class. Instead of modifying an existing object, the ClassBuilder creates a new one with the correct structure (i.e., from the new class that replaces the old one). It then fills this new object with the values of the old one. The ClassBuilder uses the become: primitive (cf 2.1.1) to proceed with the strutural modifications, by replacing the old objects with the new ones throughout the entire system.

Related

Why is objc_duplicateClass marked "Do not call this function yourself"

The documentation for objc_duplicateClass reads simply
Used by Foundation's Key-Value Observing. Do not call this function yourself.
with no elaboration or explanation. I read the source, but didn't see anything in it that that gave me any indication for why you shouldn't call it, except a few theories; except that load and initialize don't get called for classes created by objc_duplicateClass?
It seems like you could produce pretty much the same effect by calling objc_allocateClassPair with no extra bytes for additional ivars, and then immediately registering it. So what's special about objc_duplicateClass? Or, to rephrase the question, if, hypothetically, I wanted to build KVO, or something very similar, on top of the objc runtime, would it be safe to to use objc_duplicateClass?
objc_duplicateClass does pretty much what it says on the tin: it produces a new class which is a copy of the class that you give it. This includes copying the methods that the old class had, all of its metadata bits, and even its metaclass.
You couldn't recreate this behavior with objc_allocateClassPair because objc_allocateClassPair registers a new metaclass for the class you create, among other things like initializing the class — it is meant to create a new class. objc_duplicateClass creates a copy; the "new" class is not initialized any further and does not get a new metaclass because the original one already did.
As for why objc_duplicateClass is documented the way that it is: to discourage its use. objc_duplicateClass has some rare use cases, and will almost never be what you want. If you find a need for it, use it, but keep in mind that there are subtleties to the implementation you may not be aware of.
Even I marked the Q as opinion based, I'd like to try an answer:
A. Such a statement usually marks a function (or whatever) to be obsolete and is planned to be removed in future.
B. Indeed, there is no reason for this function. I do not agree with your statement, that registering a new class with zero extra bytes would do the job. because maybe there are extra bytes and you have to copy all instance var descriptions and methods manually.
However, I had to deal with such situations as KVO in the past. I have never used objc_duplicateClass(), because t is much easier and akin of cleaner to create a subclass and then make the instance a member of that subclass. You can do isa-swizzling for that calling object_setClass(id object, Class cls).
Think of a situation, obviously it is yours, that another technology wants to do something like KVO, too. Duplicating a class using objc_duplicateClass() takes not part on future dynamic changes of the original class. Maybe a method is added to it. A duplication would not add this method, too.
So objc_duplicateClass() is not useful and a bad approach.

Are the instance variables the new global variables?

lately I'm having the feeling that instances variables have the same problems of global variables, I googled about this and found this old article that more or less describes the potential problem i'm seeing.
What good practices do you use to avoid that the same problems of global variables affect instance variables or class variables?
Classes are much smaller than global structure so the impact of an instance variable is much smaller. By keeping small class sizes and adhering closely to the single responsibility principle, much of the downside of a global variable is averted. If the instance variable is created from a passed in parameter then I often make that parameter required in the constructor making the dependency explicit. Also the instance variable is encapsulated well, never being directly modified outside of the instance's methods making it very easy to determine where the instance variable is modified. Finally the instance variable must make sense to the class as a whole or must be private.
Instance variables are only accessible within a specific class. So to prevent instance variables being used too widely, keep classes small. If a class grows large, decide if parts of it that can be refactored into another, smaller class, that the original class uses.
Nor Instance variables nor global variables nor any kind of variable have "problems"... They are all tools. The problem is that sometimes a lot of programmers choose to use the "wrong tool". You have to think carefully what your choices mean, so you can make the right choice.
Using a global variable for something, like CurrentUserName... Means that you are saying that he CurrentUserName is something universally know. And that "there can be only one" CurrentUserName at each time. And that will probably be false if you ever want to allow to users to be logged at the same time (unless you get really lucky, and both users have the same name)...
A realted wrong use with instance variables is if you put the e-mail address of a User as an instance variable, and you then realize that each user can have multiple e-mail addresses.
I'd also give an example with inheritance, because I think it'll make it more clear:
A related problem with inheritance is for example if you are modeling the typical Student, Teacher problem, and you try making Student a subclass of Person and Teacher a subclass of Person. And then you realize that some persons might be both...
Student inheriting from Person is a static relationship that can't be changed at runtime. And Student and Teachers aren't static relationships... A person can be neither, and then start being a student, and then start being a teacher, and then stop being both, and yet it'll always be the same person, and that model can't handle that....
Coming back to the user, the user is "associated" with multiple e-mails account... If you put an instance variable you are stating that he is just "associated" with a single e-mail account, and you are contradicting your problem domain, and that's why you'll have problem...
The same applies if you say there is just a globally known current user name....
The problem in all cases is that you have a problem domain, and you are modeling it wrong... You have to make your program, and your model, behave similar to the problem domain.... If you don't do it, you'll have problems, whichever tool you choose to solve your problem.
BTW: I also think that User having a list of e-mail address is wrong, but that's for an entirely different set of motives. I'd actually use a
class ContactInformation
{
User contact;
EMailAddress email;
}
and remember that objects don't "own" nor "have" other objects... That's an implementation decision... Objects just "know" other objects...

"Finding" an object instance of a known class?

My first post here (anywhere for that matter!), re. Cocoa/Obj-C (I'm NOT up to speed on either, please be patient!). I hope I haven't missed the answer already, I did try to find it.
I'm an old-school procedural dog (haven't done any programming since the mid 80's, so I probably just can't even learn new tricks), but OOP has my head spinning! My question is:
is there any means at all to
"discover/find/identify" an instance
of an object of a known class, given
that some OTHER unknown process
instantiated it?
eg. somthing that would accomplish this scenario:
(id) anObj = [someTarget getMostRecentInstanceOf:[aKnownClass class]];
for that matter, "getAnyInstance" or "getAllInstances" might do the trick too.
Background: I'm trying to write a plugin for a commercial application, so much of the heavy lifting is being done by the app, behind the scenes.
I have the SDK & header files, I know what class the object is, and what method I need to call (it has only instance methods), I just can't identify the object for targetting.
I've spent untold hours and days going over Apples documentation, tutorials and lots of example/sample code on the web (including here at Stack Overflow), and come up empty. Seems that everything requires a known target object to work, and I just don't have one.
Since I may not be expressing my problem as clearly as needed, I've put up a web page, with diagram & working sample pages to illustrate:
http://www.nulltime.com/svtest/index.html
Any help or guidance will be appreciated! Thanks.
I have the SDK & header files, I know what class the object is, and what method I need to call (it has only instance methods), I just can't identify the object for targetting.
If this is a publicly declared class with publicly declared instance methods (i.e., you have the header for the class and it has instance methods in it), there is probably a way in this application's API to get an instance of the class. Either you are meant to create one yourself, or the application has one (or more) and provides a way to get it (or them). Look at both the header for the class in question and the other headers.
I initially said “there must be a way…”, but I changed it, because there is an alternative reason why the header would have instance methods: The application developer does not intend those instance methods for plug-in use (and didn't mark them appropriately), or did not mean to include that header in the application/SDK (they included it by accident). You may want to ask the application developer for guidance.
If it is not a publicly declared class or its instance methods are not publicly declared, then the application does not support you working with instances of the class. Doing so is a breach of the API contract—not a legal contract, but the expectations that the application has of its plug-ins. If you breach the API contract, you will cause unexpected behavior, either now (not necessarily on your own machine/in your own tests) or in the future.
If the class's public declaration contains only class methods, then perhaps what you're after is not an instance at all—you're supposed to send those messages to the class itself.
This is not possible without having you register each instance in a dictionary as it is created. I.e., override some common factory method at a higher level which does this bookkeeping work. This will fall down when you use delegates that you may not control though, keep that in mind.
I do question the need to even do this at all, but I don't know your problem as well as I perhaps would need to, to recommend a different, more apt way of accomplishing the actual task at hand.
Just as a corollary to the above; I did look at the runtime to see if there was anything that I actually forgot about, but there is not. So my above statement with regards to you requiring to do that bookkeeping yourself, still holds I'm afraid.
Edit:
Based on your diagram (my apologies, just noticed the link after I posted this answer); I would suggest that if you control the classes that are being returned to you, just add a property to them. I.e., add a "name" property that you can set and keep unique. Then just pass the message to each instance, checking whether or not that object is the one you want. It's not particularly clever or anything like that, but it should work for your purposes.

Reading a pointer from XML without being sure the relevant Obj-C instance exists

I have a "parent" Obj-C object containing (in a collection) a bunch of objects whose instance variables point to one another, possibly circularly (fear not, no retaining going on between these "siblings"). I write the parent object to XML, which of course involves (among other things) writing out its "children", in no particular order, and due to the possible circularity, I replace these references between the children with unique IDs that each child has.
The problem is reading this XML back in... as I create one "child", I come across an ID, but there's no guarantee the object it refers to has been created yet. Since the references are possibly circular, there isn't even an order in which to read them that solves this problem.
What do I do? My current solution is to replace (in the actual instance variables) the references with strings containing the unique IDs. This is nasty, though, because to use these instance variables, instead of something like [oneObject aSibling] I now have to do something like [theParent childWithID:[oneObject aSiblingID]]. I suppose I could create an aSibling method to simplify things, but it feels like there's a cleaner way than all this. Is there?
This sounds an awful lot like you are re-inventing NSCoding as it handles circular references, etc... Now, there might be a good reason to re-invent that wheel. Only you can answer that question.
In any case, sounds like you want a two pass unarchival process.
Pass 1: Grab all the objects out of the backing store and reconstitute. As each object comes out, shove it in a dictionary or map with the UID as the key. Whenever an object contains a UID, register the object as needing to be fixed up; add it to a set or array that you keep around during unarchival.
Pass 2: Walk the set or array of objects that need to be fixed up and fix 'em up, replacing the UIDs with objects from the map you built in pass #1.
I hit a bit of parse error on that last paragraph. Assuming your classes are sensibly declared, they ought to be able to repair themselves on the fly.
(All things considered, this is exactly the kind of data structure that is much easier to implement in a GC'd environment. If you are targeting Mac OS X, not the iPhone, turning on GC is going to make your life easier, most likely)
Java's serialization process does much the same thing. Every object it writes out, it puts in a 'previously seen objects' table. When it comes to writing out a subsequent reference, if it's seen the object before, then it writes out a code which indicates that it's a previously seen object from the list. When the reverse occurs, whenever it sees such a reference, it replaces it on the fly with the instance before.
That approach means that you don't have to use this map for all instances, but rather the substitution happens only for objects you've seen a second time. However, you still need to be able to uniquely reference the first instance you've got written, whether by some pointer to a part in the data structure or not is dependent on what you're writing.

What do you call a method of an object that changes its class?

Let's say you have a Person object and it has a method on it, promote(), that transforms it into a Captain object. What do you call this type of method/interaction?
It also feels like an inversion of:
myCaptain = new Captain(myPerson);
Edit: Thanks to all the replies. The reason I'm coming across this pattern (in Perl, but relevant anywhere) is purely for convenience. Without knowing any implementation deals, you could say the Captain class "has a" Person (I realize this may not be the best example, but be assured it isn't a subclass).
Implementation I assumed:
// this definition only matches example A
Person.promote() {
return new Captain(this)
}
personable = new Person;
// A. this is what i'm actually coding
myCaptain = personable.promote();
// B. this is what my original post was implying
personable.promote(); // is magically now a captain?
So, literally, it's just a convenience method for the construction of a Captain. I was merely wondering if this pattern has been seen in the wild and if it had a name. And I guess yeah, it doesn't really change the class so much as it returns a different one. But it theoretically could, since I don't really care about the original.
Ken++, I like how you point out a use case. Sometimes it really would be awesome to change something in place, in say, a memory sensitive environment.
A method of an object shouldn't change its class. You should either have a member which returns a new instance:
myCaptain = myPerson->ToCaptain();
Or use a constructor, as in your example:
myCaptain = new Captain(myPerson);
I would call it a conversion, or even a cast, depending on how you use the object. If you have a value object:
Person person;
You can use the constructor method to implicitly cast:
Captain captain = person;
(This is assuming C++.)
A simpler solution might be making rank a property of person. I don't know your data structure or requirements, but if you need to something that is trying to break the basics of a language its likely that there is a better way to do it.
You might want to consider the "State Pattern", also sometimes called the "Objects for States" pattern. It is defined in the book Design Patterns, but you could easily find a lot about it on Google.
A characteristic of the pattern is that "the object will appear to change its class."
Here are some links:
Objects for States
Pattern: State
Everybody seems to be assuming a C++/Java-like object system, possibly because of the syntax used in the question, but it is quite possible to change the class of an instance at runtime in other languages.
Lisp's CLOS allows changing the class of an instance at any time, and it's a well-defined and efficient transformation. (The terminology and structure is slightly different: methods don't "belong" to classes in CLOS.)
I've never heard a name for this specific type of transformation, though. The function which does this is simply called change-class.
Richard Gabriel seems to call it the "change-class protocol", after Kiczales' AMOP, which formalized as "protocols" many of the internals of CLOS for metaprogramming.
People wonder why you'd want to do this; I see two big advantages over simply creating a new instance:
faster: changing class can be as simple as updating a pointer, and updating any slots that differ; if the classes are very similar, this can be done with no new memory allocations
simpler: if a dozen places already have a reference to the old object, creating a new instance won't change what they point to; if you need to update each one yourself, that could add a lot of complexity for what should be a simple operation (2 words, in Lisp)
That's not to say it's always the right answer, but it's nice to have the ability to do this when you want it. "Change an instance's class" and "make a new instance that's similar to that one" are very different operations, and I like being able to say exactly what I mean.
The first interesting part would be to know: why do you want/need an object changes its class at runtime?
There are various options:
You want it to respond differently to some methods for a given state of the application.
You might want it to have new functionality that the original class don't have.
Others...
Statically typed languages such as Java and C# don't allow this to happen, because the type of the object should be know at compile time.
Other programming languages such as Python and Ruby may allow this ( I don't know for sure, but I know they can add methods at runtime )
For the first option, the answer given by Charlie Flowers is correct, using the state patterns would allow a class behave differently but the object will have the same interface.
For the second option, you would need to change the object type anyway and assign it to a new reference with the extra functionality. So you will need to create another distinct object and you'll end up with two different objects.