taskease.js - Tasks: task #12089, Non-virtual methods by default

 
 

You are not allowed to post comments on this tracker with your current authentication level.

task #12089: Non-virtual methods by default

Submitter:  Mike Gerwitz <mikegerwitz>
Submitted:  Sat 09 Jun 2012 11:54:21 PM UTC
   
 
Should Start On:  Sat 09 Jun 2012 04:00:00 AM UTC Should be Finished on:  Sat 09 Jun 2012 04:00:00 AM UTC
Category:  Core Priority:  5 - Normal
Item Group:  Development Status:  Done
Privacy:  Public Assigned to:  mikegerwitz
Percent Complete:  100% Open/Closed:  Closed
Planned Release:  None
Keywords:  virtual, methods

Sat 09 Jun 2012 11:54:21 PM UTC, original submission:  

Note: this task has been added for historical significance (from an earlier bug tracker). It has already been completed and will be immediately closed.




The current ease.js implementation follows languages like Java and PHP in that all class methods are virtual by default. That is, subtypes are free to override the method as they please. There are two ways to prevent this behavior:

  • Declare the method as `final`
  • Declare the class as final (`FinalClass`)


where the latter implies the former. However, this method introduces a number of design problems. A method should not be overridden unless careful consideration has been made in order to ensure that the state of the object can be properly controlled, data can remain encapsulated, clear instructions for overriding can be provided, etc. If all methods can be overridden by default, there is no such consideration. Instead, new developers are unaware of the issue and experienced developers are likely to forget to declare methods/classes as final where necessary. This is a problem and topics like inheritance should be approached carefully, if not avoided altogether in favor of composition.

As such, ease.js will make all methods non-virtual (final) by default. The C++-style syntax will be adopted in order to declare a virtual method, which may be overridden:


    Class( 'Foo',
    {
        // cannot be overridden
        'public finalFoo': function() {},

         // CAN be overridden
        'virtual public foo': function() {},
    } );


This should make developers aware of the issue, hopefully cause them to consult the documentation or wonder why such a precaution is needed, and make clear necessary design decisions to avoid poorly constructed classes.

In addition, ease.js will draw from languages such as Delphi, D and C# and adopt the `override` keyword. This will allow the developer to explicitly state that they intended to override the method. This will server as valuable documentation, make glancing over code much simpler and make the developer aware of the consequences of their actions. Errors will be thrown if the override keyword is used to attempt to override a non-virtual method, if it is used to override a non-existent method or if it is forgotten on a virtual method.


    Class( 'SubFoo' ).extend( Foo,
    {
        'override public foo': function() {},
    } );



Unlike other implementations, overrides in ease.js will be final (non-virtual). In order to permit overriding an override, one must declare it as `virtual override`. This is in contrast to, for example, C#, which requires that a method be "sealed" to prevent it from being further overridden. ease.js will take this approach to ensure that the same thought goes into overriding methods of subtypes.

This also brings up the issue of versioning. What if class `Foo` is released and inherited by subtype `SubFoo`, which implements method `bar()`. Later on, `Foo` decides to implement `bar()` as well. Suddenly, there is a conflict. Did the developer intend to override `Foo.bar()`? In this case, no. C# introduces the concept of a `new` keyword (I have never personally used C#, so I've read the specification and attempted to understand its use the best I could). This keyword can be used for method hiding rather than overriding, which can permit classes to vary independently of subtypes without breaking backwards compatibility. Developers of the subtypes may then decide what changes need to be made. More information can be found in Section 8.3 of ECMA-334. As a free software developer, I am uncomfortable using anything patented or developed as proprietary, however Microsoft has released ECMA-334 under their Community Promise, permitting its use in free software.

The concept of final classes is still useful and, as such, `FinalClass` will be preserved, preventing the class from ever being inherited.

It is important that this consideration be made before the first release (v0.1.0) to ensure backward compatibility in the future. Making this change after a release would stifle adoption as users struggle to cope with broken code. Hopefully users of ease.js, once they understand the "evils" of inheritance, will understand and come to agree with this decision. This may seem to be a bit of an awkward implementing in the sense that JavaScript is by nature very permissive in regards to modifying objects with its prototype model. Nonetheless, if we're going to be implementing a classical object model, it may as well be done properly and encourage good practices.

Mike Gerwitz <mikegerwitz>
Group administrator

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

No files currently attached

 

Depends on the following items: None found

Digest:
   task dependencies.

 

Carbon-Copy List
  • -email is unavailable- added by mikegerwitz (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

     

    Follow 2 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2012-06-09 mikegerwitz Dependencies- task #12088 is dependent
    2012-06-09 mikegerwitz Open/ClosedOpen Closed

    Back to the top

    Powered by Savane 3.13-bb6a.
    Corresponding source code