【问题标题】:Static variable inheritance in Javascript (ES6)Javascript (ES6) 中的静态变量继承
【发布时间】:2016-01-26 07:25:20
【问题描述】:

我试图弄清楚 Javascript 如何完全支持 OOP。幸运的是我可以通过 Babel 找到一些线索,并且知道它是如何向下兼容 ES5 的。

但我发现继承中的静态变量行为很奇怪。

例如,我想记住超类中的全局属性。但似乎从子类访问的静态变量实际上并不是指超类。这在经典 OOP 中合理吗?

class Animal {
  constructor(){
    this.constructor.count += 1;
    console.log('An animal was born');
  }

  static count = 0;
  static sum = function(){
    console.log('There are', this.count, 'animals');
  }

}

class Cat extends Animal{
  constructor(){
    super(); // throws exception when not called
    console.log('  -- the animal is a cat');
  }
}

var cat1 = new Cat();
var cat2 = new Cat();

Cat.sum();    // should be 2
Animal.sum(); // should be 2, but result is 0

in Babel Experimental Mode


上面是实验语法。 然后我看到一篇文章说 ES6 还不支持静态属性。所以我按照他的示例重写为静态方法(getter/setter),样式,但仍然不知道......

class Animal {
  constructor(){
    this.constructor.countOne();
    console.log('An animal was born');
  }

  static countOne(){
    this.count = (this.count||0)+1;
  }

  static sum(){
    console.log('There are', this.count, 'animals');
  }
}

Animal.count = 0; // Remove this, Animal.sum() will be undefined

class Cat extends Animal{
  constructor(){
    super();
    console.log('  -- the animal is a cat');
  }
}


var cat1 = new Cat();
var cat2 = new Cat();

Cat.sum();    // should be 2
Animal.sum(); // should be 2, but result is 0

ES6 Fiddle

“this”指的是子类,不是超类,结果是一样的……


此外,我在 PHP 中尝试了相同的代码,然后得到了预期的结果:

class Animal{
  static $count = 0;
  static function sum(){
    echo "There are " . self::$count . " animals <br>";
  }

  public function __construct(){
    self::$count++;
    echo "An animal was born <br>";
  }
}

class Cat extends Animal{
  public function __construct(){
    parent::__construct();
    echo " - the animal is a cat <br>";
  }
}

$cat = new Cat();
$cat = new Cat();
$cat = new Cat();

Cat::sum();     // is 3
Animal::sum();  // is 3

到目前为止,我们应该说Javascript不支持静态变量继承吗?甚至在 ECMA6 中?

有什么优雅的解决方案吗?

【问题讨论】:

  • 但是你的js代码和你的php不同
  • 简而言之:this.countself-&gt;count 相同,而不是 self::count
  • 是的!我在问我们如何在JS中使用self::count之类的东西,但不能直接通过类名访问,例如:Animal.count,这似乎违反了封装原则
  • 静态类成员首先不是对象的一部分。那么为什么Animal.count 会破坏封装呢?通过self:: 引用静态成员基本上是自欺欺人(没有双关语)。

标签: javascript oop inheritance ecmascript-6


【解决方案1】:

您可以访问静态成员,例如:

Animal.count;
Animal.countOne();
Animal.sum();

在第二个示例中,当您创建新猫时,this 指的是新猫对象,this.constructor 指的是 Cat 函数(即使它是从超级构造函数调用的)。

【讨论】:

  • 这不是 OP 询问的静态继承。如果支持静态继承,您将能够编写:Animal.count,并取回一个值。
【解决方案2】:

还有另一种提供静态属性的方法,那就是通过闭包。通过将您的类定义包装在一个函数中,您可以将变量的范围仅限于您的类,从而有效地创建一个私有静态变量。

例如

"use strict";
var log =function(d){console.log(d)}; // lazy zoo keeper

// need to define the intermediate container
// Ill call it zoo.
var zoo = (function() {
    // now create the private static property
    var count=0;  // function scoped
    class Animal {
        constructor(){
            count += 1; // count instances
            log('An animal was born');
        } 
        static sum(){  // create the static method of interagation
            log('There are'+count+'animals');
        }

     }

     class Cat extends Animal{
         whatAreYou(){log("I am a cat ")};
     }
     // now return the classes you want to expose 
     return {
         Animal:Animal,
         Cat:Cat,             
     };
})();  // call the function to create a  Zoo

// now you can make the the Animal and Cat public or you could 
// keep zoo and pass it to another scope and have them private 
// where you want.

var Animal = zoo.Animal;
var Cat = zoo.Cat;

// Use static function befor there are any instances of Animal or Cat
Animal.sum(); // displays 0    

var a = new Animal(); // or new zoo.Animal();
var c = new Cat();

// access static function sum to display content of private and static (closure) property count;
Cat.sum();    // 2
Animal.sum(); // 2

【讨论】:

    猜你喜欢
    • 2011-03-29
    • 1970-01-01
    • 2019-04-28
    • 2020-10-18
    • 2011-04-24
    • 1970-01-01
    • 2016-09-10
    • 2017-01-10
    • 1970-01-01
    相关资源
    最近更新 更多