Defines a class using a `superclass`, `constructor`, methods and/or static methods.
@format sjl.defineSubClass (superclass, methodsAndConstructor, statics);
@format sjl.defineSubClass (superclass, constructor, methods, statics);
@function module:sjl.defineSubClass
@param superclass {Function} - Superclass to inherit from.
@param constructor {Function|Object} - Required.  Note:  If this param is an object, then other params shift over by 1 (`methods` becomes `statics` and this param becomes `methods` (constructor key expected else empty stand in constructor is used).
@param methods {Object|undefined} - Methods for prototype.  Optional.  Note:  If `constructor` param is an object, this param takes the place of the `statics` param.
@param statics {Object|undefined} - Constructor's static methods.  Optional.  Note:  If `constructor` param is an object, this param is not used.
@example
```
// sjl.defineSubClass (superclass, methods, statics);
var NewConstructor = sjl.defineSubClass( SomeConstructor, { constructor: function SomeOtherConstructor () {}, ...}, {...});

// sjl.defineSubClass (superclass, constructor, methods, statics);
var NewConstructor = sjl.defineSubClass( SomeConstructor, function SomeOtherConstructor () {}, {...}, {...});

// Both calls above yield extendable constructors;  E.g.,
// This call yields another constructor which inherits from NewConstructor and is also extendable (has `extend` static method).
NewConstructor.extend(AnotherConstructor)

```
@returns {Function}
function defineSubClass (superClass, constructor, methods, statics) {
        var _constructor_ = defineSubClassPure.apply(null, arguments);

        // set overridden `toString` method and set `extend` and `extendWith` methods after create a
        // pure sub class of `superClass`
        return compose(makeExtendableConstructor, classicalToStringMethod)(_constructor_);
    }