JObject



JObject

Hierarchy
The base class type that is ancestor to all other classes

Description

In traditional object pascal all classes must inherit from TObject right? No matter what you do you just could not escape that fact. Unless you used records, defined functions as fields and mapped the entry points manually. Which we sometimes have to do when talking to old-school C libraries or esoteric kernel code, but that's another matter. TObject is the mother of all classes, thats the general rule (or was).

In Smart Mobile Studio you can use the whole inheritance system inside the compiler and get rid of TObject as the ultimate ancestor and instead use a JObject as ancestor class.


Interesting

JavaScript does not support true OOP in the ordinary sense of the word, which makes it exceedingly difficult for classical web-designers to create reusable components or manage large scale projects.
Javascript programmers sometimes want to add new properties (or methods) to an existing object. Sometimes want to add new properties (or methods) to all existing objects of a given type or sometimes want to add new properties (or methods) to an object prototype.

Smart Mobile Studio delivers full OOP running under JavaScript and offer a way to programming using OOP prototype approach-like. The compiler technology generates a real-life VMT (virtual method table) in JavaScript, which means that you can write objects and inherit from them just like you do in Delphi.


Object is thus the new root class, above TObject. Eventually, it'll be the ancestor for every other type.

JObject

The earliest need for migrating to a rooted type system was to unify TObject and the new JObject, which is is the new root class for all "prototypal inheritence" JavaScript classes in SmartMS(while TObject remains the root for classical Pascal classes).

Subclasses of JObject are either purely external classes (implemented on the JS side, in the DOM, etc.) or Pascal classes compiled to JavaScript, but that follow the JavaScript "object" conventions rather than the Pascal conventions, ie.

  • methods are resolved through prototype (they can be resolved either statically or via a VMT for TObject)
  • field and method names are not obfuscated
  • no smart-linking or de-virtualization can occur
  • they are globally scoped in JS
  • marking methods as "virtual" is an error (they are dynamic, which is a bit like being implicitly "virtual" and "overridden")
  • visibility isn't supported (on the JS-side)
  • ClassType, ClassName, etc. don't exist

These classes are intended primarily for consumption by "external" JavaScript libraries.

They'll look and behave like "pure" JavaScript classes, so will share their downsides (no obfuscation, no whole-program optimizations, no elimination of unused methods by the smart-linker, etc.); Still, they retain some Smart Pascal advantages (strong typing, local optimizations, obfuscation of method implementations, case insensitivity on the Pascal side).

Here is the quick and dirty example:
I'm using consolidated unit syntax for compacity (but you could use classic interface/implementation as well).
type
  myLib = class(JObject)
  private
	HelloText : String = 'hello';
  published
	procedure sayHello(s : String);
	begin
	  ShowMessage(HelloText+' '+s);
	end;
  end;
  
{ main.pas }
var obj : myLib;
Begin
  obj := new myLib;
  obj.sayHello('JObject as Ancestor class'); 

JS output:
function $Extend(base, sub, props) {
	function F() {};
	F.prototype = base.prototype;
	sub.prototype = new F();
	sub.prototype.constructor = sub;
	for (var n in props) {
		if (props.hasOwnProperty(n)) {
			sub.prototype[n]=props[n];
		}
	}
}

function myLib() {
}
$Extend(Object,myLib,
   {
	  "HelloText" : "hello",
	  /// procedure myLib.sayHello(s: String)
	  ///  [line: 51, column: 15, file: uMain]
	  "sayHello" : function(s) {
		 alert(this.HelloText+" "+s);
	  }
   });

	  var obj = null;
	  obj = new myLib();
	  obj.sayHello("JObject as Ancestor class");