JQuery UI 继承多态

JQuery UI inheritance polymorphism

在jQuery UI中的小部件的继承中有没有办法具有多态性?

例如我想做这样的事情:

$.widget('tr.fatherClass', {
  getValue: function() {
    return null;
  }
  ...
});
// sonClass1: extends from the father
$.widget('tr.sonClass1', $.tr.fatherClass, {
  getValue: function() {
    return this._fooFunction1();
  }
  ...
});
// sonClass2: extends from the father
$.widget('tr.sonClass2', $.tr.fatherClass, {
  getValue: function() {
    return this._fooFunction2();//
  }
  ...
});
// create an instance of a "sonClass"
$('#foo1').sonClass1(options);  
$('#foo2').sonClass2(options);  

那我想用方法"getValue"不知道儿子的名字class:

$('#foo1').fatherClass('getValue'); // run _fooFunction1() of sonClass1
$('#foo2').fatherClass('getValue'); // run _fooFunction2() of sonClass2

但这是不可能的:

jquery.js:250 Uncaught Error: cannot call methods on variable prior to initialization; attempted to call method 'getValue'

在 JQuery 的论坛中,Scott Gonzalez 解释说“创建一个小部件只会创建一个小部件,而不是原型链中的每个小部件link

有任何解决方法或解决方案可以优雅地完成此操作吗?

在 OOD 中,支持组合而不是继承很重要。但是如果你仍然想要多态性,而不是切换插件,你可以创建一个函数作为插件变量,你可以在你的应用程序逻辑中覆盖

示例:

$.widget('myWidget', {
    getValue: function() {
      if(userfunc != null)
         return userfunc();
      return null;
   }
   userfunc: null
  });

然后你可以为 userfunc 创建不同的版本

userfunc1 = function(){  return 43; }
userfunc2 = function(){  return 38; }

$('#foo').myWidget({userfunc : userfunc1})
value = $('#foo').myWidget('getValue') <= returns 47

$('#foo').myWidget({userfunc : userfunc2})
value = $('#foo').myWidget('getValue') <= returns 38

希望对您有所帮助

无法从小部件声明外部访问父级的方法,但如果您自己编写了 sonClass,则可以使用 this._super() 从父级调用相同的方法,实现在您的 sonClass 看起来像这样...

// extends from the father
$.widget('tr.sonClass', $.tr.fatherClass, {
  getValue: function( fromFather ) {
    if ( 'father' == fromFather ) { // If 'father' is passed as argument
      return this._super(); // Get the result from father's method
    } else {
      return this._$input.val();
    }
  }
  ...
});

你可以这样调用父亲的方法...

console.log( $('#foo').sonClass('getValue', 'father') );

供参考
http://api.jqueryui.com/jQuery.widget/#method-_super

更新

我们向父亲添加新的 fathersMethod 方法,该方法 returns 来自父亲...

$.widget('tr.fatherClass', {
  //Add this to father to get properties from father
  fathersMethod: function(prop) {
    if ( typeof $.tr.fatherClass.prototype[prop] == 'function' )
    return $.tr.fatherClass.prototype[prop]();
  },
  getValue: function() {
    return 'yellow'; // Father likes yellow
  },
  ...
  ...
  ...
});

现在对于任何继承自父亲的儿子(或女儿)...都可以像这样调用父亲的方法...

$('#foo').sonClass('fathersMethod', 'getValue');

这是更新后的代码段 ;-)

$.widget('tr.fatherClass', {
  fathersMethod: function(prop) {
    if ( typeof $.tr.fatherClass.prototype[prop] == 'function' )
    return $.tr.fatherClass.prototype[prop]();
  },
  getValue: function() {
    return 'yellow'; // Father likes yellow
  }
});

// extends from the father
$.widget('tr.sonClass', $.tr.fatherClass, {
  getValue: function() {
    return 'blue'; // Son likes blue
  }
});

// extends from the father
$.widget('tr.daughterClass', $.tr.fatherClass, {
  getValue: function() {
    return 'pink'; // Daughter likes pink
  }
});

// This is son
$('#foo').sonClass();

// This is daughter
$('#bar').daughterClass();

// Son's fav color
console.log( $('#foo').sonClass('getValue') );

// Son's FATHER's fav color
console.log( $('#foo').sonClass('fathersMethod', 'getValue') );

// Daughter's fav color
console.log( $('#bar').daughterClass('getValue') );

// Daughter's FATHER's fav color
console.log( $('#bar').daughterClass('fathersMethod', 'getValue') );
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<div id='foo'></div>
<div id='bar'></div>

通常你在这里所说的多态性是标准的继承和实例化行为。

$('#foo1').sonClass1(options);  
$('#foo2').sonClass2(options);  

创建两个不同的 class 实例。

foo1.getValue 将执行实例化的 classes,这里 sonClass1getValue 定义(代码块)是 fooFunction1.

foo2.getValue 将执行实例化的class,这里是 sonClass2getValue 定义(代码块)是 fooFunction2。

以后来电这里

$('#foo1').fatherClass('getValue'); // run _fooFunction1() of sonClass1
$('#foo2').fatherClass('getValue'); // run _fooFunction2() of sonClass2

不是调用 sonClass1sonClass2 getValue 方法定义,而是调用 fatherClass .

您通常希望在上述两种情况下使用父亲的 getValue 方法定义。

然而你的错误说它是未定义的。

我不使用 JQuery 但我怀疑它的继承机制不会实例化父 class。

我们用过js的都遇到过这个问题,也通过各种方式解决了。

您可以将 fatherClass 另存为 data 用于具有某些键的元素,例如 fatherObject 它应该进入父亲的 _create() 方法...

$.widget('tr.fatherClass', {
  _create: function(){
    $(this.element).data( 'fatherObject', $.tr.fatherClass.prototype );
  },
  ...
};

稍后使用...检索值...

$('#foo').data('fatherObject').getValue()

$('#bar').data('fatherObject').getValue()

$.widget('tr.fatherClass', {
  _create: function(){
    $(this.element).data( 'fatherObject', $.tr.fatherClass.prototype );
  },
  getValue: function() {
    return 'yellow'; // Father likes yellow
  }
});

// extends from the father
$.widget('tr.sonClass', $.tr.fatherClass, {
  getValue: function() {
    return 'blue'; // Son likes blue
  }
});

// extends from the father
$.widget('tr.daughterClass', $.tr.fatherClass, {
  getValue: function() {
    return 'pink'; // Daughter likes pink
  }
});

// This is son
$('#foo').sonClass();

// This is daughter
$('#bar').daughterClass();

// Son's fav color
console.log( $('#foo').sonClass('getValue') );

// Son's FATHER's fav color
console.log( $('#bar').data('fatherObject').getValue() );

// Daughter's fav color
console.log( $('#bar').daughterClass('getValue') );

// Daughter's FATHER's fav color
console.log( $('#bar').data('fatherObject').getValue() );
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<div id='foo'></div>
<div id='bar'></div>