关于self 类的应用

class A
  C = 1
end
class B < A
  class << self
    def test1
      puts C
    end
  end
  def self.test2
    puts C
  end
  def test3
    puts C
  end
end


=begin
主要来看下一下几种输出,看他们的结果都有什么样的?

 p B.test1
 p B.test2
 我们来执行下这段代码输出就发现,会报错: in `test1': uninitialized constant Class::C (NameError)
 为什么会报这个错误的?
 我们会有疑问?
 为什么在test2或者test3中可以直接使用C,在test1中就不能使用那?

 p B.test2
 p B.new.test3
 p B.test3
 我们来执行下这段代码输出的时候就发现,会报错: undefined method `test3' for B:Class (NoMethodError)
 我们又会产生疑问了?
 为什么test2 和 test3的调用方法不一样那?

 先Hold的问题,听下面的一些讲解,你就会明白了。这块内容主要涉及到以下几点的内容

 a. 关于类常量的作用域,以及使用范围
    以大写字母打头的标识符是常量,对常量进行二次赋值解释器会提示警告,
    而引用未被赋值的常量实抛出 NameError 异常。
    在类、模块外部定义的常量属于 Object,可以使用“::常量名”
    引用属于 Object 的常量,以“模块名/类名::常量名”的形式引用外部的常量
    类内直接使用,继承类的类方法内直接使用类常量,继承类的类实例方法必须使用 类/模块::常量

    下面就要说下什么是类方法?什么又是实例方法?

 b. 关于类方法,形如一下格式:
     def 类名.方法
        ***********
     end
    这个表示是属于类专用的方法,不属于类对象的方法, 使用:类名.方法
    class B < A
       def self.test2
           puts C
       end
    end
   同价于:
   class B < A
       def B.test2
           puts C
       end
    end
    调用:
         B.test2

 c. 实例方法
    class B < A
       def test3
           puts C
       end
    end
    这个是我们习惯性的写法,这个是属于类实例方法,属于类对象的专属方法,类不能直接使用。
    调用用到时候必须先实例化,new一个对象,然后调用。
    如: B.new.test3

 d. 关于类对象追加方法用法
    给特定的类对象追加方法或者属性,这些方法和属性是直接封装到一个类中,直接追加到对象中。
    这个类没有特定的名字,所以不能像普通的类一样使用。
    格式如下:
      Class << obj
      end
    本例中使用如下:
    class B < A
        class << self
          def test1
            puts C
          end
       end
    end
   这个里面我们使用到了<< 和self,   << 是追加的意思,self的含义:当前对象,或者是默认对象
   这个虚拟类(元类 metaclass)的self指的的是什么那?
    self这个在虚拟类中指的默认对象是:#<Class:B>
    self这个在虚拟类中的test1方法中指的默认对象是:B,如同在class B中的self

   这个是用到了ruby的单件类或叫metaclass 也有叫singletonclass。
   这个类的执行环境就相当于不在Class B中了,虽然写在这个位置。从self可以看出他们的执行对象是不同的。

 e. 关于继承
    这个就不多讲了,A<B 就是A继承了B ,A 是B的子类,可以使用A的所有资源,A可以重写父类方法。如同java的继承。
   Ruby是单继承的,但是也能实现多继承的可以实现的一切。。

  使用Model模块,在类中include 模块 就能达到多继承的效果了。

现在我们再来看代码:

下面我们来分析下test1 test2 test3 三个方法:

我们主要来看下他的执行环境吧,即class执行的一个有效范围吧,即 self对象指的是什么东西?
 test1: 是B的单例类的方法。 这个特殊类的执行环境是在B类外的。
 test2: 是类方法,B继承了A,就继承了C,可以在类的方法(类方法和类实例方法)中使用。执行环境是Class B中
 test3: 是B的类对象方法,执行环境是类B中:Class B ---> end

所以在test1中使用常量,就相当于在类外使用类常量了。
   使用方式如下:A::C 或者B::C 或者self::C
为什么可以使用self::C那?
 因为test1方法中的self 指的是:B 等价于 使用B::C,B继承A,写成A::C也是ok的
=end


### 3.1 `self`在面向对象编程中的使用方式 在Python的面向对象编程中,`self`是一个约定俗成的参数名称,用于表示的实例本身。它必须作为中定义的每个实例方法的第一个参数,用于绑定该方法调用时的对象。通过`self`,可以访问和修改实例的属性以及其他方法。 例如,在的构造函数`__init__`中,通过`self`可以初始化实例变量: ```python class Dog: def __init__(self, name): self.name = name # 通过 self 初始化实例属性 ``` 此外,`self`还允许调用中的其他方法,实现对象行为的组合和交互: ```python class Dog: def __init__(self, name): self.name = name def bark(self): print(f"{self.name} says woof!") # 通过 self 访问实例属性 ``` ### 3.2 `self`与共享属性的关系 共享属性通常是指属性,它们属于本身而不是特定的实例。属性可以通过名直接访问,也可以通过实例访问。`self`在这种情况下可以用于访问属性,但不会修改属性的值,除非显式地通过名进行修改。 例如: ```python class Dog: species = "Canis familiaris" # 属性,共享于所有实例 def __init__(self, name): self.name = name dog1 = Dog("Buddy") dog2 = Dog("Max") print(dog1.species) # 输出 "Canis familiaris" print(dog2.species) # 输出 "Canis familiaris" ``` 在上述代码中,`species`是属性,通过`self.species`可以访问。每个实例都可以访问该属性,但不会影响其他实例的值,因为属性是共享的。 ### 3.3 `self`的应用场景 `self`的主要应用场景包括: 1. **实例属性的初始化**:在`__init__`方法中使用`self`来初始化实例属性,这些属性属于特定实例,每个实例拥有独立的副本。 2. **访问和修改实例属性**:在的方法中,通过`self`可以访问和修改实例的属性。 3. **调用其他方法**:在的方法中,通过`self`可以调用其他方法,实现更复杂的行为组合。 4. **继承中的使用**:在子中,通过`super()`函数和`self`可以调用父的方法,确保继承链中的属性和方法正确初始化和执行。 例如,在继承中使用`self`: ```python class Animal: def __init__(self, name): self.name = name class Dog(Animal): def __init__(self, name, breed): super().__init__(name) # 通过 super() 和 self 调用父构造方法 self.breed = breed ``` ### 3.4 `self`在方法与静态方法中的限制 尽管`self`在实例方法中广泛使用,但在方法和静态方法中其角色有所不同。方法的第一个参数是`cls`,表示本身而非实例,因此不能直接通过`self`访问实例属性。静态方法则不接收任何隐式参数,既不能使用`self`也不能使用`cls`,主要用于封装与相关但不依赖实例状态的功能。 例如: ```python class Calculator: @classmethod def class_method(cls): print(f"Called from {cls}") @staticmethod def static_method(): print("Static method called") ``` 在方法中,`cls`用于访问属性和方法;在静态方法中,不依赖任何实例或上下文,因此不能通过`self`访问对象状态。 ### 3.5 `self`的作用总结 综上所述,`self`在Python中主要用于绑定实例属性、访问属性、调用其他方法以及在继承中传递实例上下文。它确保了每个实例拥有独立的状态,同时支持共享属性的访问。通过`self`,Python实现了面向对象编程的核心机制,包括封装、继承和多态。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值