百科问答小站 logo
百科问答小站 font logo



ES6的class关键字有没有实现真正的面向对象? 第1页

  

user avatar   rednaxelafx 网友的相关建议: 
      

很多“纯面向对象厨”还吐槽像Java、C#的静态方法不面向对象呢。“真正的面向对象”语言里所有操作都应该有receiver,静态方法没有receiver所以不面向对象。

——你们想怎么定义哪种模型更面向对象都罢,俺只管用,怎么样好用都行…

回到题主的问题,每个问题都可以换个角度来争辩:<- 再次声明,俺对这些争辩不感冒,既不支持题主的论点也不是说下面争辩的观点就对。只要是规定得规整的设计俺都OK。

1. 类没有静态属性;

也可以说有静态属性更不面向对象。

类自身是对象,类对象可以有字段,这就很足够了,非常面向对象。

2. 类的静态方法,实例无法调用;

在“真正的面向对象”语言里,类也是一个对象,所谓“静态方法”不过就是挂在类对象上的方法而已。要调用它们就指定该类为receiver去调用即可。ES6的class正好就可以做到这点,很面向对象。

像Java、C#的静态方法没有receiver,是一种比较不面向对象的设计。要从面向对象的角度看,它们可以看作是依赖静态类型系统来去省略了作为receiver的类参数的折衷设计,而它们其实也是要通过“ClassName.methodName(...)”的方式来调用的,只不过Java和C#在名字查找规则上对静态方法做了特殊处理,允许在实例方法里省略类名去调用本类的静态方法。在像ES6这样动态的语言里,这种隐式指定receiver的做法反而不现实也不直观。

Java的语法里还有一种非常恶心的调用静态方法的办法——通过一个实例的引用去调用:

       public class Foo {   static void bar() { }   void baz() {     this.bar(); //=> actually compiles into Foo.bar()   }    public static void main(String[] args) {     Foo obj = null;     obj.bar(); //=> actually compiles into Foo.bar(), no NPE thrown   } }     

这里 Foo.bar() 是一个静态方法,但我们可以用调用实例方法的语法(this.bar()、obj.bar())去调用它——而实际的语义跟那个引用一点关系都没有,纯粹是一个静态方法调用而已。这就是为什么当引用是null的时候用这种语法调用静态方法还是可以正常编译并运行,而不会在运行时抛出NullPointerException。这个设计非常糟糕,很容易就把读代码的人骗了,以为这里调用的是实例方法。这绝对不是什么好的面向对象设计。

3. 只能在方法内定义属性;

这跟是否面向对象其实关系不大,而是跟语言的动态性更有关系。

看看同样也很动态的Python和Ruby,它们也都是只能在实例方法里定义实例字段。像Ruby的attr_accessor只是声明了某个名字的getter / setter(合起来叫做accessor),但却没有定义实例字段自身。这只不过是一种动态的设计风格,谈不上面向对象与否。




  

相关话题

  如何看待faker.js 开源作者删除了所有的代码? 
  JavaScript(V8,Node) 的开发效率比 Java(JVM,Vert.x) 高在哪里? 
  大一新生如何自学JavaScript? 
  2022 年,学完 JS 高级后的学习路线怎样规划? 
  为什么 Vue 的更新记录没有中文,中文文档也一直滞后? 
  c#中没有友元类那么这种设计是否不太合理,如何修改才能得到更好的方案? 
  如何看待鸿蒙应用开发框架采用JavaScript作为开发语言? 
  JavaScript 关于 if…else if…else 的疑问? 
  为什么 JS 不能绕过后端代码直接调数据库,有哪些后端处理的逻辑,JS 不能写? 
  Typescript 如何使一个传入的 Array 类型变为元组类型? 

前一个讨论
如何撩学数学的妹子?
下一个讨论
女权主义者如何看待结婚男女双方金钱付出的不对等?婚姻?





© 2024-05-18 - tinynew.org. All Rights Reserved.
© 2024-05-18 - tinynew.org. 保留所有权利