[gjs] Class: introduce abstract classes



commit 95947ea7eca0b740a728214584300dd82e394e77
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Sun Nov 20 13:31:46 2011 +0100

    Class: introduce abstract classes
    
    By setting Abstract: true in the class parameters, you can now
    obtain a class that will throw upon instantiation. The class can
    still have an _init (that derived class can call) and otherwise works
    like all other classes.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=664437

 modules/lang.js      |   23 +++++++++++++++--------
 test/js/testClass.js |   39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+), 8 deletions(-)
---
diff --git a/modules/lang.js b/modules/lang.js
index 695d448..344720e 100644
--- a/modules/lang.js
+++ b/modules/lang.js
@@ -178,22 +178,29 @@ function Class(params) {
     if (!params.Name) {
         throw new TypeError("Classes require an explicit 'name' parameter.");
     }
+    let name = params.Name;
 
-    let newClass = function() {
-        if (!this._init)
-            return this;
-
-        return this._init.apply(this, arguments);
-    };
+    let newClass;
+    if (params.Abstract) {
+        newClass = function() {
+            throw new TypeError('Cannot instantiate abstract class ' + name);
+        };
+    } else {
+        newClass = function() {
+            if (!this._init)
+                return this;
+
+            return this._init.apply(this, arguments);
+        };
+    }
 
     let parent = params.Extends;
     if (!parent)
         parent = _Base;
-    let name = params.Name;
 
     let propertyObj = { };
     let propertyDescriptors = Object.getOwnPropertyNames(params).forEach(function(name) {
-        if (name == 'Name' || name == 'Extends')
+        if (name == 'Name' || name == 'Extends' || name == 'Abstract')
             return;
 
         let descriptor = Object.getOwnPropertyDescriptor(params, name);
diff --git a/test/js/testClass.js b/test/js/testClass.js
index c5f5110..06c37d3 100644
--- a/test/js/testClass.js
+++ b/test/js/testClass.js
@@ -68,6 +68,32 @@ const Accessor = new Lang.Class({
     }
 });
 
+const AbstractBase = new Lang.Class({
+    Name: 'AbstractBase',
+    Abstract: true,
+
+    _init: function() {
+        this.foo = 42;
+    }
+});
+
+const AbstractImpl = new Lang.Class({
+    Name: 'AbstractImpl',
+    Extends: AbstractBase,
+
+    _init: function() {
+        this.parent();
+        this.bar = 42;
+    }
+});
+
+const AbstractImpl2 = new Lang.Class({
+    Name: 'AbstractImpl2',
+    Extends: AbstractBase,
+
+    // no _init here, we inherit the parent one
+});
+
 function testClassFramework() {
     let newMagic = new MagicBase('A');
     assertEquals('A',  newMagic.a);
@@ -126,4 +152,17 @@ function testAccessor() {
     assertEquals(42, newAccessor.value);
 }
 
+function testAbstract() {
+    assertRaises(function() {
+        let newAbstract = new AbstractBase();
+    });
+
+    let newAbstract = new AbstractImpl();
+    assertEquals(42, newAbstract.foo);
+    assertEquals(42, newAbstract.bar);
+
+    newAbstract = new AbstractImpl2();
+    assertEquals(42, newAbstract.foo);
+}
+
 gjstestRun();



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]