FPC PasCocoa/Differences

From Lazarus wiki
Jump to navigationJump to search

Introduction

FPC's "Objective-Pascal" (ObjCPas) dialect was introduced to enable seamless interfacing with Objective-C code, in particular on Mac OS X. Due to inherent differences between the C and Pascal philosophies, this language mode will have some seemingly strange behaviour regardless of whether your main background is in Objective-C or in Object-Pascal.

This page describes the conceptual differences between ObjCPas and on the one hand Objective-C, and on the other hand Object Pascal.

Differences with Object Pascal

No constructors

No destructors

No unique root class

  • Description: In Object Pascal, if you do not specify a parent class, a newly defined class will automatically inherit from TObject. While in NeXTStep/Apple/GNUStep's Objective-C frameworks NSObject fulfills a similar role, there are also other root classes (such as NSProxy). Since there is no unique root class in the Objective-C language, this means that if you do not specify a parent class, you will define a new root class.
  • What to do: Generally, you will want new classes to inherit from NSObject if they do not have to inherit from any other class.

Differences with Objective-C

Marking methods as override

  • Description: In Object Pascal, if you want to override an inherited method then you have to add the override keyword to the declaration in the child class. Without override, the inherited method will be hidden in the syntactic scope of the child class, but when casting the child class to the parent type and call that method, the parent's implementation will still be executed.

      In Objective-C all dispatching is name-based, and hence a method with the same selector in a child class will always override a parent method with the same name (unlike in Object Pascal, it is not possible to hide an inherited method, nor to start a new inheritance tree).

      Objective-Pascal however also requires override to be specified when overriding inherited Objective-C methods for consistency with Object Pascal. If override is absent, the compiler will give an error. This can also help catch bugs, as explained in this thread. There is one exception though: for external classes, override is not required because such declarations are often produced using automated parsers, and requiring them to add override in the right places could needlessly complicate them. Not adding override in such situations will however still cause the compiler to show a hint.

  • What to do: Always add override; at the end of method declarations that override inherited methods.

Class instances are implicit pointers

  • Description: In (Delphi-style) Object Pascal, all class instance variables are implicit pointers, and they are also implicitly dereferenced. In Objective-C, class instances are explicitly declared as being "a pointer to a class instance", e.g. NSObject *obj; and need to be explicitly dereferenced when accessing instance variables (although this seldom happens, since most of the time accessors or properties are used).
  • What to do: Do not use any explicit indirection when dealing with Objective-Pascal class instances.

Duplicate identifiers

  • Description: Pascal allows an identifier to appear only once per scope, and treats a class declaration as a single scope. This means that all instance variables, class methods, instance methods and properties must have distinct names. In Objective-C, each of those categories has its own namespace and there is no problem with having an instance method, class method and instance variable all named foo in a single class. Similarly, a class and a protocol can also have the same name (such as the NSObject class and protocol).
  • What to do: On the Pascal-side, all such identifiers must be made unique. In case of methods, these can easily be mapped to the real names used the corresponding in Objective-C code due to the fact that the selector has to be specified explicitly anyway. We will probably add the ability to specify mappings for instance variables. The real name of an Objective-C class or protocol can be specified by specifying a name along with the external modifier at the end of the type declaration.
  • Example:

<delphi> type

 NSObjectProtocol = objcprotocol
    // "_class" instead of "class" on the Pascal side, because "class" is a language keyword
    function _class: pobjc_class; message name 'class';
 end; external name 'NSObject'; // specify the real name of this protocol
 NSObject = objcclass(NSObjectProtocol)
   function _class: pobjc_class; // no need to specify the selector again, it's copied by the compiler from the protocol definition
   // "classClass" (or something else) instead of "_class" because otherwise there are
   // two methods with the same name in the NSObject class.
   class function classClass: pobjc_class; message 'class';
 end; external; // name specification is optional since NSObject is the real name

</delphi>