FSClass Reference

This page lists all the methods implemented by the FSClass bundle.

FSClass Reference

FSClass is a special object that supports the creation of new classes. All methods in this section apply to the singleton FSClass object.

Classes are created by calling one of the following methods on the object FSClass:

+ (Class) newClass

Creates a new "anonymous" class. The name of this class, as retrieved by the Foundation method +className, will be automatically generated.

+ (Class) newClass:(NSString*)className

Creates a new class with a specific name. This method will throw an error if the supplied name is already in use.

+ (Class) newClassWithParent:(Class)parent

Creates an anonymous subclass of the supplied parent class, which may be either an FSClass or a compiled Objective-C class.

+ (Class) newClass:(NSString*)className parent:(Class)parent

Creates a new class with a supplied class as parent. This method will throw an error if the supplied name is already in use.

+ (Class) newClass:(NSString*)className properties:(NSArray*)propertyNames

Creates a new class that inherits from NSObject and uses optimized property accessor methods. These 'fast-ivar' classes store properties directly inside the object, just like regular Objective-C classes; if one of the above class creation methods is used, an NSDictionary object as intermediary. As a result, the overhead for property access is dramatically lower. If you know exactly what properties a class needs, use this method to create the class.

"Properties" in FSClass-derived classes are not exactly like Objective-C 2.0 properties; there is no special syntax in F-Script for accessing properties, so all instance data must be accessed using the normal Key-Value compliant

All elements of the iVars array must be strings; if they are not, this method will throw an exception.

Note: As of FSClass 2.0, fast-ivar classes are not compatible with the GUI F-Script interpreter. If you are using the GUI interpreter, use regular classes instead with newClass:parent:.

FSClass also has several methods that expose part of the Objective-C runtime functionality:

+ (SEL) selectorFromString:(SEL)selector do:(id)block

Given a method name, returns a selector in compact block form. Works like the Foundation function NSSelectorFromString. This method will throw an exception if the string is not a valid F-Script selector.

+ (NSString*) stringFromSelector:(SEL)selector

Converts a selector (in compact block form) into a string. Works like the Foundation function NSStringFromSelector. sys log:(FSClass stringFromSelector:#doFoo:). will print foo:

+ (Class) getClass:(NSString*)className

Returns the class that has the given name. Works like the Foundation function NSClassFromString. Returns nil if there is no class with that name.

Class Introspection and Modification

All classes created through FSClass have methods that support adding properties and methods, and retrieving information about them.

Subclassing

The following two methods can be used to create new F-Script based classes:

+ (Class) subclass

Creates a new, anonymous subclass of the receiver.

+ (Class) subclass:(NSString*)name

Creates a new subclass of the receiver with the provided name.

Adding Methods

These commands are used to add new instance methods, or to replace the implementations of existing instance methods. Methods cannot be removed from classes.

+ (void) onMessage:(SEL)selector do:(id)block

Adds a method to a class. When specified message is sent to an instance of the class, the supplied F-Script block will be run. The block should take self as its first argument, and must have one additional argument for each parameter in the selector.

+ (void) onMessageName:(NSString*)messageName do:(id)block

Like onMessage:do:, but takes a string that contains the name of a selector, rather than the selector itself. MyClass onMessage:#doStuff: do:... is equivalent to MyClass onMessageName:'doStuff:' do:.... If messageName is not a valid selector name, this method will throw an error. If you are implementing methods for operators (like + or =), you must use the appropriate mapped names (e.g. operator_plus: and operator_equals:).

Adding Properties

Methods in this section are used to add instance properties to classes.

+ (void) addProperty:(NSString*)propertyName

Add a property to a class. The property can be accessed by the KVC-compliant methods propertyName and setPropertyName:. To maintain Key-Value Coding compliance, the supplied property names should follow the KVC guidelines; see the Key-Value Coding Programming Guide for more details.

Properties cannot be removed from a class, but they can be added dynamically after the class is created. All existing instances of the class created before a property is added will subsequently be able to access that property. The default value of the property is nil.

If you created the class with FSClass newClass:properties:, you will not be able to use addProperty: or other related methods; they will throw exceptions if you call them.

+ (void) addProperty:(NSString*)propertyName withDefault:(id)defaultValue

Add a property to a class, with a default value. This default value will be assigned to the property when a new instance is created with new. If all your class' init method does is set simple default property values, you can assign them when declaring the properties and omit a custom init method.

It is extremely important that if you use default property values, they must be immutable. Valid classes for default values include NSString, NSNumber, NSArray, NSDictionary, NSDate, and NSValue. The reason for this restriction is that the single object supplied as a default is actually shared between instances, not copied, and if mutable objects are used, a change to one will affect all instances. As such, the use of immutable values will be unpredictable.

+ (void) addPropertiesWithDefaults:(NSArray*)propertiesWithDefaults

A shortcut for adding multiple properties with defaults at once. The array should have the following format:

{ 'propertyOneName', propertyOneDefault, 'propertyTwoName', propertyTwoDefault, ... }

The method will throw an exception if the array contains an odd number of elements.

+ (void) addPropertiesFromDictionary:(NSDictionary*)propertyDictionary

Adds all of the key/value pairs from the dictionary to the class as property names and default values. The keys for the dictionary must all be strings. The following code creates an anonymous class that can access dictionary keys from a configuration plist file:

tempClass := FSClass newClass.

tempClass addPropertiesFromDictionary:(NSDictionary dictionaryWithContentsOfFile:'config.plist').

config := tempClass new.

(config debug) ifTrue:[
    ....
].
+ (id) defaultValueForProperty:(NSString*)propertyName

Returns the default value for a property, including those of parent classes. The default value will be nil if none has been set. If the property does not exist in the class or parent classes, this method will throw an exception.

+ (void) setDefaultValue:(id)defaultValue forProperty:(NSString*)propertyName

Sets the default value for an instance property. All new instances will have this property as the default; existing instances will not be changed. This class will throw an exception if the class does not have the property; unlike -defaultValueForProperty:, this method will not search through superclasses to find the property.

Class Properties and Methods

Properties created with FSClass also can have class properties and methods.

+ (void) onClassMessage:(SEL)selector do:(id)block

Adds a method to the class itself. onClassMessage:do: should be used to create class factory methods, which will be responsible for creating actual objects with alloc init.

+ (void) addClassProperty:(NSString*)propName withValue:(id)value

Adds a property to the class itself, with an initial value. The property can be accessed by the methods propName and setPropName:, just like instance properties.

+ (void) addClassProperty:(NSString*)propName

Equivalent to class addProperty:'propName' withValue:nil.

Introspection

Classes created with FSClass also have a full suite of introspection commands that can be used to retrieve information about methods and properties

+ (NSArray*) methods

Returns an array of selectors (in the form of compact blocks) that the class implements, including those inherited from superclasses. Does not include the methods that implement property access, or any methods inherited from Objective-C superclasses, including NSObject.

+ (NSArray*) allMethods

Returns all the methods implemented by this class and any F-Script-based superclasses.

+ (NSArray*) methodNames

Like methods, but returns an array that contains methods names as strings, rather than selectors. Does not include the methods that implement property access, or any methods inherited from Objective-C superclasses, including NSObject.

+ (NSArray*) allMethodNames

Returns the names of all the methods implemented by this class and any F-Script-based superclasses.

+ (NSArray*) propertyNames

Returns the names of the class's instance properties. This method does not include properties inherited from parent classes; if you want all property names for the class, use the method -allPropertyNames instead.

Note that this method will only return the names of properties created in F-Script; Objective-C 2.0 properties will not be included.

+ (NSArray*) allPropertyNames

Returns the names of the class's instance properties, including properties inherited from superclasses. Objective-C 2.0 properties will not be included.

+ (Class) methodImplementor:(SEL)selector

Given a (non-property-related) selector that the class supports, returns the first class in the inheritance hierarchy that implements that method. If the method is not recognized by the class, returns nil. For example, say that we have the following classes, and that they implement the given methods:

ClassImplemented Methods
ClassAdoAstuff:doOtherAstuff:
ClassBdoAstuff:doBstuff:
ClassCdoCstuff:

methodImplementor: would return the following results:

CodeResult
ClassC methodImplementor:#doAstuff:ClassB
ClassC methodImplementor:#doOtherAstuff:ClassA
ClassC methodImplementor:#doCstuff:ClassC
ClassB methodImplementor:#doAstuff:ClassB
ClassB methodImplementor:#doOtherAStuff:ClassA
ClassB methodImplementor:#doCstuff:nil
+ (id) blockForSelector:(SEL)selector

Given a (non-property-related) selector that the class supports, returns the Block that implements the method (possibly from a superclass). If the method is not supported, or is implemented by an Objective-C superclass, returns nil.

Class Introspection

The following methods provide introspection capabilities for class methods and properties. They return similar values as the instance introspection methods above.

+ (NSArray*) classMethods
+ (NSArray*) allClassMethods
+ (NSArray*) classMethodNames
+ (NSArray*) allClassMethodNames
+ (NSArray*) classPropertyNames
+ (NSArray*) allClassPropertyNames
+ (Class) classMethodImplementor:(SEL)selector
+ (id) blockForClassSelector:(SEL)selector

Manipulating Objective-C Classes

All of the methods described above can also be used with Objective-C classes. Unlike with FSClass 2.0, creating a proxy is not necessary; the methods can be applied directly to the class object itself:

NSString onMessage:#bork do:[ :self |
    "Return a borked version of self"
    self ++ '! bork bork bork!'
].

The introspection capabilities of Objective-C classes apply only to methods created in F-Script. For example, if you have not added any additional methods to NSObject, the code NSObject methodNames will return an empty array.

Objective-C classes cannot use the introspection methods that deal with instance properties. The following reflection methods cannot be used with classes written in Objective-C:

The class property versions of these methods, however, can be used with Objective-C classes.


Copyright 2007-2208 Andrew Weinrich