Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/469.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 重命名子类中的父类属性_Javascript_Class_Inheritance_Ecmascript 6 - Fatal编程技术网

Javascript 重命名子类中的父类属性

Javascript 重命名子类中的父类属性,javascript,class,inheritance,ecmascript-6,Javascript,Class,Inheritance,Ecmascript 6,在es2015中,如果我有基类来表示如下所示的列表: class List { constructor(data){ this.data = data } sortBy(attribute){ return this.data.sort((a,b) => { return (a[attribute] < b[attribute]) ? 1 : -1; }) } get count() { return this.data.le

在es2015中,如果我有基类来表示如下所示的
列表

class List {
  constructor(data){
    this.data = data
  }

  sortBy(attribute){
    return this.data.sort((a,b) => {
      return (a[attribute] < b[attribute]) ? 1 : -1;
    })
  }
  get count() { return this.data.length }
}
class List {
  constructor(data){ this.data = data; }
  sortBy(attribute){
    console.log("sortBy");
    return this.data.sort( (a,b) => {
      if (a[attribute] < b[attribute]) return -1;
      if (a[attribute] > b[attribute]) return 1;
      return 0;
    });
  }
  get count() { return this.data.length; }
}
此时,除了名称之外,
ToyList
List
没有区别。但是如果您查看
ToyList
的实例化,它既有
数据
又有
玩具
属性。就概念化
ToyList
的点而言,
data
没有多大意义,它们指的是同一个数组

如果我制作了一个
ToyList
,我就同时拥有
.data
.toys
属性:

tl = new ToyList(['truck', 'plane', 'doll'])
Object { data: Array[3], toys: Array[3] }
那么我的
tl
既有
data
又有
toys
属性。它们都是对同一数组的引用,但我希望子类只具有
toys
引用

下面是另一个在基类上使用方法的示例:

class Todos extends List {
  constructor(todos){
    super(todos);
    this.todos = todos;
  }

  get byPriority(){
    return this.todos.sortBy('priority')
  }
}

var thingsToDo = [
  {task: 'wash the dog', priority: 10},
  {task: 'do taxes', priority: 1},
  {task: 'clean the garage', priority: 0}

]

var todos = new Todos(thingsToDo);
todos.byPriority
这将很好,因为这样我就可以参考
.byPriority
,获得列表的排序版本,它非常特定于这种特殊类型的数据。但我看不出我怎么能做到,因为

但我得到的是:

TypeError: this.todos.sortBy is not a function

总之,我想要的是一种引用基类属性的方法,该属性的名称特定于子类的语义,而不会丢失基类的方法。

引用我们在评论中的讨论,一个更好的实现(imo),可扩展并避免您所问的问题

var AP = Array.prototype; //just lazy

class List {
    constructor(elements){
        for(var i = 0, j = (elements && elements.length)|0; i<j; ++i)
            this[i] = elements[i];
        //use length instead of count, stay compatible with the Array-methods
        //will make your life easier
        this.length = i;
    }

    length: 0

    sortBy(attr){
        return this.sort(function(a,b){
            return (a[attribute] < b[attribute]) ? 1 : -1
        });
    }

    //some functions have to be wrapped, to produce a List of the right type
    filter(fn){
        return new (this.constructor)(AP.filter.call(this, fn));
    }

    clone(){ return new (this.constructor)(this) }
}

//some functions can simply be copied from Array
//no need to re-implement or even wrap them.
List.prototype.sort = AP.sort;
List.prototype.push = AP.push;
List.prototype.pop = AP.pop;
以及一个示例用法

class Toy {
  constructor(name){
    this.name = name;
  }
}

var a = new ToyList([
  new Toy("foo"), 
  new Toy("bar"), 
  "not a toy",
  new Toy("baz") 
])

console.log(a instanceof ToyList, a);

var b = a.filter(toy => toy.name.charAt(0) === "b");

console.log(b instanceof ToyList, b);
编辑:添加带有TODO的示例

class Todos extends List {
    //don't even need a constructor, since I simply want to pass 
    //the array to the parent-constructor

    //don't use getter for functionality, use methods!
    byPriority(){
        return this.sortBy('priority');
    }
}

var thingsToDo = [
  {task: 'wash the dog', priority: 10},
  {task: 'do taxes', priority: 1},
  {task: 'clean the garage', priority: 0}
]

var todos = new Todos(thingsToDo);
todos.byPriority()

在我看来,如果可能的话,更好的方法是将List类视为纯虚拟类,这意味着您永远不会创建该类的实例,而只是从该类扩展

纯虚拟类不应该有构造函数,方法应该假设存在某些属性。但是,实际上可以使用构造函数设置基类应用于“data”属性的名称

class List {
 constructor(keyName) { this.keyName = keyName }
 sortBy(attr) { return this[this.keyName].sort(...) } 
}

class ToyList extends List {
  constructor('toys') {
    super(toys)
    this.toys = toys;
  }
}
ToyList
既有
数据
又有
玩具
属性。就概念化
ToyList
的点而言,
data
没有多大意义,它们指的是同一个数组

这是您的实际问题:您的
ToyList
作为
List
的子类没有意义

如果(出于任何原因)您的类应该类似于
列表
,但没有
数据
属性,那么它不再是子类。这将违反法律


现在你有什么选择

  • 正如您已经考虑过的,您可以将其作为一个子类,其中更具体的
    .toys
    属性是
    .data
    的别名。这是非常好的,但是您不能避免在那里也有
    data
    属性
  • 您可能希望清除
    数据
    属性,并将元素直接存储在对象上。您的
    列表
    类看起来像“数组,但带有有用的辅助函数”。如果这是你的意图,你应该考虑把它变成一个实际的子类:代码>数组< /COD>。托马斯的回答就是这个方向
  • 你可能想优先于继承。您已经使用了这个概念-您的
    列表
    实例在其
    数据
    属性中包含
    数组
    s。如果您有一个
    愿望列表
    玩具列表
    或其他专门处理惠斯或玩具的东西,并且有相应的方法,您可以简单地将一个
    列表
    实例存储在它们的
    .toys
    插槽中。
    实际上,您似乎期望您的
    TodoList
    能够像这样工作,因为调用了
    this.todos.sortBy('priority')
    (其中
    this.todos
    将是一个
    列表
    )。在子类上,只需
    this.sortBy('priority')
    就可以完成这项工作
  • 我真的不明白你的
    ToyList
    是如何专门化
    列表的。如果它除了名称之外没有什么特别之处,那么实际上可能不需要一个不同的类。如果JavaScript有泛型或类型变量,您可以使用
    列表
    ,但事实并非如此,因此您可以直接使用
    列表

    • 我想你有很多不同的问题

      您的列表与
      的定义有问题,您需要考虑3种情况,如下所示:

      class List {
        constructor(data){
          this.data = data
        }
      
        sortBy(attribute){
          return this.data.sort((a,b) => {
            return (a[attribute] < b[attribute]) ? 1 : -1;
          })
        }
        get count() { return this.data.length }
      }
      
      class List {
        constructor(data){ this.data = data; }
        sortBy(attribute){
          console.log("sortBy");
          return this.data.sort( (a,b) => {
            if (a[attribute] < b[attribute]) return -1;
            if (a[attribute] > b[attribute]) return 1;
            return 0;
          });
        }
        get count() { return this.data.length; }
      }
      
      让我们对TODO执行相同的操作:

      class Todos extends List {
        constructor(todos){ super(todos); }
        get todos() { return data; }
        get byPriority(){
          return this.sortBy('priority');
        }
      }
      
      byPriority
      的定义有点奇怪,因为它具有边框效果(对元素进行排序)。我(个人)会把它作为一种标准方法来写

      然后让我们做一些测试:

      var thingsToDo = [
        {task: 'wash the dog', priority: 10},
        {task: 'do taxes', priority: 1},
        {task: 'clean the garage', priority: 3}
      ];
      
      var tl = new ToyList(['truck', 'plane', 'doll']);
      for (var i=0; i<3; i++) {
        console.log(tl.toys[i]); // access the *pseudo* toys attribute
      }
      
      var todos = new Todos(thingsToDo);
      var r = todos.byPriority; // access the *pseudo*  byPriority attribute (border effect: sorting internal data)
      
      for (var i=0; i<3; i++) {
        console.log(todos.data[i].priority);
      }
      
      var thingsToDo=[
      {任务:'洗狗',优先级:10},
      {任务:'纳税',优先级:1},
      {任务:“清理车库”,优先级:3}
      ];
      var tl=新玩具列表(['truck','plane','doll']);
      
      对于(var i=0;iWell,如果您不想要List提供的功能,为什么要从List继承?似乎您的抽象需要重新评估!?我在基类中添加了两个以上的方法,以便更清楚地说明这一点。当然,在集合中还会有其他方法,您可以使用主干集合来执行这些操作n、 例如(排序、搜索、保存等)。我的问题是如何重写基类上的给定属性,以便派生类可以具有特定于域的方法和属性,而不是其他任何内容。不反对在派生类上添加附加功能。但只要您不将集合应用于
      数据
      -属性,则列表将失败,您必须为派生类包装或重新实现它们;就像您使用
      get toyCount()
      而不是使用
      get count()
      所做的那样。整个方法毫无意义,只会增加复杂性。我将添加一个更好方法的示例。
      但我得到的是:TypeError:this.todos.sortBy
      
      var thingsToDo = [
        {task: 'wash the dog', priority: 10},
        {task: 'do taxes', priority: 1},
        {task: 'clean the garage', priority: 3}
      ];
      
      var tl = new ToyList(['truck', 'plane', 'doll']);
      for (var i=0; i<3; i++) {
        console.log(tl.toys[i]); // access the *pseudo* toys attribute
      }
      
      var todos = new Todos(thingsToDo);
      var r = todos.byPriority; // access the *pseudo*  byPriority attribute (border effect: sorting internal data)
      
      for (var i=0; i<3; i++) {
        console.log(todos.data[i].priority);
      }