• Ruby学习_self


    self上下文

         Ruby的self有和Java的this相似之处,但又大不相同。Java的方法都是在实例方法中引用,所以this一般都是指向当前对象的。而Ruby的代码逐行执行,所以在不同的上下文(context)self就有了不同的含义,先来看看常见的context self都代表哪些

    # 这个位置位于top level context,代表Object的默认对象main
    p self # => main
    p self.class # => Object
    @self1 = self

    # 因为所有自定义类都位于main context之中,所以这是Object的实例方法
    # 同时也可以说是一个全局方法
    def a_method
      @self2 = self
      p self
      # => main,因为有了实例变量@self1和@self2,所以打印出来的不是main这个字符
      # => 但仍然是main对象,注释掉4,8行即可看到效果
      p @self1 == @self2 # => true
    end


    # 下面是一个关于类中不同上下文的self
    class Person
      p self # => Person,代表当前类
     
      def instance_method
        p self # => #<Person:0xb7818fdc>,代表当前类的实例
      end
     
      def self.class_method
        p self # => Person,和第16行一样代表当前类(这是类方法的context),它们是相等的
      end
    end

    m = Person.new
    def m.hello
      p self # => 代表m这个单例对象
    end

    m.hello

        上面只写了在类中的self,其实在module也是一样的。通过上面代码你可以发现,self一直引用着它所在位置上下文的实例/类。

        self显式/隐式

        你可以先试着运行下面代码,看看有什么意外发生没有


     class Person
      attr_accessor :name
     
      def set_name(your_name)
        name = your_name
      end
    end

    m = Person.new
    p m.name
    m.set_name('today')
    p m.name # => 猜是什么

        如果你猜是today就大错特错了,答案是nil,为什么是nil呢,在第5行,我明明调用的是attr_accessor生成的name=方法赋值的啊,你可以在前面加上self试试,代码如你预期的一样执行了。在这种情况下name = your_name并没有去调用attr_accessor生成的xx=方法,而是将name当作了一个局部变量,如果显式的指定self,就没有问题了。

        读到这,你是不是认为以后这种情况就一直用显式self去调用就好了,其实不然,下面的代码仍会说明一些问题


     class Person

      public
      def get_my_secret1
        my_secret # => 隐式
      end
     
      def get_my_secret2
        self.my_secret # => 显式
      end

      private
      def my_secret
        p 'something...'
      end
     
      def self.secret
        p 'nothing'
      end
    end

    m = Person.new
    #m.my_secret # => private method error
    Person.secret # => nothing
    m.get_my_secret1 # => something
    m.get_my_secret2 # => private method error
     

        上面代码说明:

        第一个问题,显式self不可以调用private(protected的也一样)方法,而隐式的可以,这说明隐式更具有灵活性,但由于上面隐式调用也同时存在一定的“误解”,所以读者应该明白他们之间的区别,以便更好的使用。

        第二个问题,self的方法不受private限制,其实我在这故意误导了读者,因为self的方法是类方法,而权限修饰符只对实例方法生效,所以private的类方法也可以直接访问。

        self“怪异”写法

        下面代码被我个人称为怪异写法,因为平时用不到,但偶尔会看到,但看起来又不太直观,这里列举一下

     class Person
      def metaclass
        class << self
          self
        end
      end
     
      def metaclass2
        self
      end
    end

    a = Person.new

    b = a.metaclass
    c = a.metaclass2

    # 首先要明白,类Person是Class的一个“实例”,a是Person的一个实例
    # 这里b也是一个Person类,但它是独一无二的,即你修改Person不会影响到b,反之亦然
    p b # => #<Class:#<Person:0xb76f3800>>
    p b.class # => Class

    class Person
      def hello
        p 'hello Person'
      end
    end

    class << b
      def hello
        p 'hello b'
      end
    end

    b.hello # => hello b


    p c # => #<Person:0xb76f3800>
    p c.class # => Person

    c.hello # => hello Person
     

        还有一个

     class Person
      def self.hello
        p 'hello'
      end
     
      class << self
        # 看了最上面self和context的关系,你应该知道这个self代表是Person类
        # 在这里为Person添加方法,其实也就是为Person添加类方法,和上面的self.hello异曲同工
        def work
          p 'hard work'
        end
      end
    end

    Person.work

    转自:http://ilstar.blogbus.com/logs/59782933.html
     

  • 相关阅读:
    关于CSS自文档的思考_css声明式语言式代码注释
    html5中contenteditable属性如果过滤标签,过滤富文本样式
    web前端工程化/构建自动化
    Python连载19-装饰器
    Java连载1-概述&常用的dos命令
    HTML连载18-id选择器与class区别&class选择器使用思路&后代选择器
    Python连载18-closure闭包解释及其注意点
    HTML连载17-id选择器&类选择器
    Python连载17-排序函数&返回函数的函数
    HTML连载16-颜色控制属性2&标签选择器
  • 原文地址:https://www.cnblogs.com/puresoul/p/2363595.html
Copyright © 2020-2023  润新知