问题 JQuery UI继承多态


有没有办法在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”:

$('#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解释说“创建小部件只会创建一个小部件,而不是原型链中的每个小部件链接

有一种解决方法或解决方案以优雅的方式做到这一点吗?


10169
2018-06-30 14:18


起源

这不是jQuery插件的工作方式。你必须在同一个插件中处理你的逻辑。你从中获得了什么现实世界的优势? - T J
我可以使用相同的界面创建一个界面并控制不同类型的小部件 - Troncador


答案:


你可以保存 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>


2
2017-07-10 13:48



我的答案做了一些改变,但主要的想法正是我想要的 - Troncador


在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

希望这可以帮助


3
2017-07-04 14:00



它没有解决我的问题,但是一个很好的起点,我会考虑它 - Troncador


无法从窗口小部件声明外部访问已写入的父方法,但是如果您已经编写过 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

UPDATE

我们添加新的 fathersMethod 返回父亲的父亲的方法...

$.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>


2
2017-07-06 11:06



我澄清了一点我的问题。我没有问题在儿子中运行父亲的代码。我的问题是我有很多种儿子,我想以类似的方式控制它们。 - Troncador
更新了我的答案,想法是在父亲中创建一个接受prop参数的新方法,检查是否 prop 是一种方法 $.tr.fatherClasss原型,如果是,则调用它返回值。 - shramee
它没有解决我的问题,因为你必须知道#bar是一个子类,而#foo是一个sonClass。我的观点是忘记它并使用界面调用它们,就像我在我的问题中显示的那样。 $( '#富')fatherClass( '的getValue')。 $( '#条')fatherClass( '的getValue')。 <---在这个例子中我不关心是否有sonClass,daughterClass或fatherClass - Troncador
添加了一个新的答案来解决问题...(不想再次更新答案; P) - shramee


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

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

创建两个不同的类实例。

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

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

后来打电话到这里

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

打电话不是 sonClass1 要么 sonClass2  getValue 方法的定义,但是 fatherClass

在上述两种情况下,您通常都会期望父亲的情况 getValue 要使用的方法定义。

然而,您的错误表明它未定义。

我不使用JQuery但我怀疑它的继承机制没有实例化父类。

我们所有使用过js的人都遇到过这个问题,并以各种方式解决了这个问题。


2
2017-07-10 04:31