• 谈谈Ruby中的类变量


    Ruby中的类变量,很多文章都是不太建议使用的,主要原因在于他的一些特性容易导致犯一些错误,尤其在广泛使用元编程的时候。

    初步接触类变量可能觉得他跟C++的类静态成员和Java中的静态变量没什么区别,但在实际使用中一不留神就会掉到类变量的陷阱中去

    陷阱1,类变量跟类实例变量不同,类实例变量关联的是self,但类变量关联的是当前类作用域

    class C
    end
    
    class D
    end
    
    class C
      @@var = "C"
      def D.getvar
        @@var
      end
    end
    
    class D
      @@var = "D"
      def C.getvar
        @@var
      end
    end
    
    C.getvar
    #=> "D"
    D.getvar
    #=> "C"

    在这个例子里面我在类C里面定义D的方法,在D里面定义C的方法,结果C的方法返回了D的类变量,而D的方法返回了C的类变量,这就是由于类变量跟当前环境的self无关,只跟所在环境的类作用域有关,如果不包含在class关键字中,则视为在Object中。

    是不是感觉有点怪怪的啊,不过更怪的还在后面。

    陷阱2,超类如果增加一个子类已有的同名类变量,会将子类的类变量污染

    我们知道类的继承带有引用性质,在一个引用树上,子类可以重写超类的方法和变量而不对超类产生影响,但对于类变量这个事情不成立

    类变量在整个继承树中只有一个实体,首先超类中如果有类变量,子类完全继承,而子类中的类变量原则上是不影响超类的,但一旦超类中加入了相同的类变量就会自动把子类的类变量重写!!

    class C
      @@var1 = "C_var1"
      def getvar
        @@var1
      end
      def setvar
        @@var2 = "C_var2"
      end
    end
    class D < C
      @@var2 = "D_var2"
      def getvar
        @@var2
      end
    end
    c = C.new
    d = D.new
    p c.getvar
    #"C_var1"
    p d.getvar
    #"D_var2"
    c.setvar
    p c.getvar
    #"C_var1"
    p d.getvar
    #"C_var2"

    可以看到,子类和超类有各自的同名实例函数,但是却共享一个相同的类变量名。

    陷阱3,跟陷阱2类似,Object中如果定义一个类变量,会将所有类中的同名类变量污染

    同样的,如果两个不同的子类中有两个相同的类变量,这本来是不干扰的,但是一旦他们共同的超类定义了该类变量,这三个类变量就会强制统一!!

    而我们知道类共同的超类是Object,那么一旦你在Object中定义了一个类变量,就会导致所有的类的同名类变量都受到污染!!

    class C
      @@var = "C_var"
      def getvar
        @@var
      end
    end
    class D
      @@var = "D_var"
      def getvar
        @@var
      end
    end
    c = C.new
    d = D.new
    p c.getvar
    # "C_var"
    p d.getvar
    # "D_var"
    class Object
      @@var = "Object_var"
    end
    # @@var = "main_var"
    # 使用这句有同样的效果,不过会得到一个警告
    p c.getvar
    # "Object_var"
    p d.getvar
    # "Object_var"

    类变量在一个继承树中只能有一个,不允许重写,但在不同的继承树中却允许重名,这个奇葩的东西还是少碰点的好

    因此慎用类变量,尤其是不要用猴子补丁来定义类变量,我甚至觉得这个奇怪的东西应该从Ruby中拿掉。

  • 相关阅读:
    攻防世界pwn高手区——pwn1
    攻防世界misc——János-the-Ripper
    攻防世界逆向——game
    PWN——ret2dl_resolve
    谈一些想法
    python网络编程(一)
    pwnable.kr之unlink
    堆的数据结构探究
    记一次GKCTF之旅
    socket笔记
  • 原文地址:https://www.cnblogs.com/lancky/p/6209269.html
Copyright © 2020-2023  润新知