百科问答小站 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),但却没有定义实例字段自身。这只不过是一种动态的设计风格,谈不上面向对象与否。




  

相关话题

  python是对面向对象编程友好的语言吗?有没有改进空间? 
  如何衡量一个人的 JavaScript 水平? 
  程序员讨厌面试被问一些基础问题么? 
  为什么很多明知js的OOP是假的,还不厌其烦地实现,而不使用OLOO风格? 
  请问有什么好的C语言面向对象的扩展的方式?最好是有比较好的项目的源码参考。 
  Web 建站技术中,HTML、HTML5、XHTML、CSS、SQL、JavaScript、PHP、ASP.NET、Web Services 是什么? 
  前端开发的难点到底在什么地方? 
  用 // 代替 http:// 有什么好处? 
  如果我现在想定义Windows这个类,之后让它继承Rectangle这个类,这样做对么? 
  Java 的开发效率究竟比 C++ 高在哪里? 

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





© 2025-04-09 - tinynew.org. All Rights Reserved.
© 2025-04-09 - tinynew.org. 保留所有权利