Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
1

[Q] OOP in ExtendScript / ECMAscript 3

Explorer ,
Jan 20, 2024 Jan 20, 2024

Copy link to clipboard

Copied

Hi,

 

I am looking for some pointers and examples of what is possible in terms of OOP in ExtendScript. I'm not too lazy to Google, but Googling this info is quite hard as a lot of what pops up is for later versions of JavaScript in which OOP syntax is considerable different. I'm hoping for a clean example of what is possible in terms of inheritance and encapsulation with the state-of-the-art in 1999 🙂

 

For example, I notice that the following are not available:

Object.create()

class

 

I'm happily using this syntax:

 

function MyClass(myParameter) {
this.dataMember1 = ...;
this.dataMember2 = ...;

this.memberFunction1 = function(myParameter, myParameter) {
// do something
}

this.memberFunction2 = function(myParameter, myParameter) {
// do something
}

}

 

which works well and am interested how much further I can take this.

 

I read this:

https://alistapart.com/article/prototypal-object-oriented-programming-using-javascript/

 

which is helpful but also assumes  more modern Javascript than ExtendScript offers.

 

Any help greatly appreciated.

 

 

// Tom

 

 

TOPICS
Scripting

Views

626
Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Guide , Jan 20, 2024 Jan 20, 2024

Most, if not all, of what is in the link you posted works in ES3.  All you need is an Object.create polyfill.  You can add an

extend() function to emulate "class B extends A" in Java and ES6+ (@dolce5EC2 called it inheret()).
// polyfills
Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
};
function extend(Child, Parent) {
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Child;
}

// 1st class
var A = function (p1, p
...

Votes

Translate
Adobe
Explorer ,
Jan 20, 2024 Jan 20, 2024

Copy link to clipboard

Copied

there's an old hackaround
You should work with prototype property:

function ClassA() { }
ClassA.prototype.hello = function () {
$.writeln("o hi");
}
 
function ClassB() { }
 
 
inherit(ClassB, ClassA);
 
var b = new ClassB();
b.hello();
 
 
 
function inherit(childClass, parentClass) {
function F() { }
F.prototype = parentClass.prototype;
childClass.prototype = new F();
childClass.prototype.constructor = childClass;
childClass.super = parentClass.prototype;
}

Votes

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jan 20, 2024 Jan 20, 2024

Copy link to clipboard

Copied

Most, if not all, of what is in the link you posted works in ES3.  All you need is an Object.create polyfill.  You can add an

extend() function to emulate "class B extends A" in Java and ES6+ (@dolce5EC2 called it inheret()).
// polyfills
Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
};
function extend(Child, Parent) {
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Child;
}

// 1st class
var A = function (p1, p2) {
    this.p1 = p1;
    this.p2 = p2;
};
A.prototype.f1 = function () {
    return "f1 is called by " + this.p1 + this.p2;
};

// 2nd class (using inheritance)
var B = function (p1, p2) {
    // this.p1 = p1;
    // this.p2 = p2;
    // or, call super constructor, A:
    A.call(this, p1, p2);
};
extend(B, A);  // B inherits A's prototype

// creating objects
var a1 = new A("a", 1);
var b1 = new B("b", 1);

// accessing objects
alert(
    a1.f1()  /*f1 is called by object1*/
    + "\n" +
    b1.f1()  /*f1 is called by object2*/
);

Votes

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jan 20, 2024 Jan 20, 2024

Copy link to clipboard

Copied

Dear Dolce and Femke,

 

Many thanks, really useful.

@m h av72176891: I don't see you use the Object.create in your sample code. Why/when is the Object.create polyfill needed?

 

And these polyfills (Object.create and extend) do I only need them once? Where do you put them?

 

And in terms of best practices: do you put every class in a single file?

 

 

Votes

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jan 20, 2024 Jan 20, 2024

Copy link to clipboard

Copied

Object.create is used in defining extend().  If you want to use it directly in the above example, you can use

B.prototype = Object.create(A.prototype);

instead of

extend(B, A);

and B will inherit the functions in A's prototype.

 

The pollyfills are used once and go right at the top of the script.  Or, you can put them in a separate file with any other pollyfills you regularly use (and access them with #include).  Java and JS conventions say that each class should be a separate file, but this can be ignored, of course.

Votes

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jan 20, 2024 Jan 20, 2024

Copy link to clipboard

Copied

Thank you so much, Femke, this is all really very helpful.

 

Votes

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 20, 2024 Jan 20, 2024

Copy link to clipboard

Copied

Thanks @femkeblanco, this helped me understand too! 🙂

- Mark

Votes

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jan 22, 2024 Jan 22, 2024

Copy link to clipboard

Copied

@tomd75724979 @m1b You're welcome.  If you're interested, I found the crouse Ultimate JavaScript Part 2: Advanced Topics by Mosh Hamedani to be the easiest intro to OOP-like JavaScript.  The first part of the course is available on YouTube for free, but not the parts on prototypes and prototypal inheritance.  Still, you can check to see if it's not too basic for you.  The good thing about it is that it uses pre-ES6 JavaScript for the most part, which you can emulate with pollyfills (e.g. Object.create, Object.assign, etc), although there are some things ES3 just can't emulate. 

Votes

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 22, 2024 Jan 22, 2024

Copy link to clipboard

Copied

Thanks!

Votes

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jan 23, 2024 Jan 23, 2024

Copy link to clipboard

Copied

Super useful, Femke, thank you so much. I'm going to have a look at this. At the moment, I'm trying to wrap my head around how far to take OOP with ExtendScript. My kneejerk reflex is to write wrappers for some of the most common ExtendScript objects (say PathItem) but maybe with prototypal inheritance that approach is not so good?

 

Also, I'm wondering about how to handle actions on multiple objects. Say I have two instances of PathItem and I want to do a subtract (Boolean difference). Would I want to write a class to handle that? Or do I just fall back to procedural processing in the main thread, using a subtract menu command directly?

 

I'm aware this is probably more of a software architecture question that an OOP syntax question 🙂

Votes

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jan 29, 2024 Jan 29, 2024

Copy link to clipboard

Copied

I keep it simple.  I use "classes" when I want to create many objects with similar properties, for example here.  I use inheritance when I have many classes with similar functions, which is admittedly not common.  I think there is some value in learning about prototypes, even if you don't use them, because you will come across cool scripts that do.  Apart from that, there is the satisfaction of just understanding the concept of prototypes, which many Javascripters don't.  (I can't help you with the question about actions.  I don't think I have used actions in scripts.) 

Votes

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 29, 2024 Jan 29, 2024

Copy link to clipboard

Copied

LATEST

Hi @tomd75724979, a few notes:

 

1. I often write wrappers around Illustrator objects, but the one's I make aren't anything like a "sub-class" like you might make in other environments (or that Femke described). This may say more about me than anything generally.

 

2. I *almost never* use any form of inheritance—it just hasn't seemed useful for my projects. Again, this may not be a general experience for people. EDIT: oops, I mean to say I don't use inheritance aside from the built-in prototypal inheritance—I use that A LOT. 🙂

 

3. Inheritance and hierarchy has nothing *inherently* (no pun intended!) to do with object oriented programming. I find OOP *extremely* useful and yet I almost never need inheritance.

 

4. As @femkeblanco discusses, using prototypes is a good tool we have to express OOP principals.

 

With OOP we ask question such as "what does this object (by itself) know about?" and "what does this object (by itself) know how to do?" and "what are the relationships between this object and that object". These concepts are important: "What does the class know, versus what does each instance know?" and "What can the class do, versus what can each instance do?"

- Mark

Votes

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines