docs: function addMethod(name, method, constructor, opts) {
          var metadata,
              isStatic = opts && opts.isStatic,
              target;
  
          // Check if it is a private member
          if (name.substr(0, 2) === '__') {
              throw new Error('Abstract class "' + constructor.prototype.$name + '" contains an unallowed abstract ' + (isStatic ? 'static ' : '') + 'private method: "' + name + '".');
          }
          // Check if it contains implementation
          if (!isFunctionEmpty(method)) {
              throw new Error((isStatic ? 'Static method' : 'Method') + ' "' + name + '" must be anonymous and contain no implementation in abstract class "' + constructor.prototype.$name + '".');
          }
  
          target = isStatic ? constructor : constructor.prototype;
  
          // Check if function is ok
          metadata = functionMeta(method, name);
          if (metadata === null) {
              throw new Error((isStatic ? 'Static method' : 'Method') + ' "' + name + '" contains optional arguments before mandatory ones in abstract class "' + constructor.prototype.$name + '".');
          }
  
          // Check if a variable exists with the same name
          target = isStatic ? constructor[$class].staticProperties : constructor[$class].properties;
          if (isObject(target[name])) {
              throw new Error('Abstract method "' + name + '" defined in abstract class "' + constructor.prototype.$name + '" conflicts with an already defined property.');
          }
  
  
          target = isStatic ? constructor[$class].staticMethods : constructor[$class].methods;
  
          // Check if it is already implemented
          if (isObject(target[name])) {
              throw new Error('Abstract method "' + name + '" defined in abstract class "' + constructor.prototype.$name + '" seems to be already implemented and cannot be declared as abstract anymore.');
          }
  
          target = isStatic ? constructor[$abstract].staticMethods : constructor[$abstract].methods;
  
          // Check if the method already exists and if it's compatible
          if (isObject(target[name])) {
              if (!isFunctionCompatible(metadata, target[name])) {
                  throw new Error((isStatic ? 'Static method' : 'Method') + ' "' + name + '(' + metadata.signature + ')" defined in abstract class "' + constructor.prototype.$name + '" overrides its ancestor but it is not compatible with its signature: "' + name + '(' + target[name].signature + ')".');
              }
          }
  
          if (!isStatic && method[$bound]) {
              insert(constructor[$class].binds, name);
          }
  
          metadata.checkCompatibility = true;
  
          target[name] = metadata;
      }