`

实例方法和类方法(三)

    博客分类:
  • Ruby
阅读更多

这一次,让我们搞一些破坏性实验,来验证上两次的内容

第一个破坏性实验,module里定义self.xxx方法

ruby 代码
  1. irb(main):001:0> module M   
  2. irb(main):002:1> def self.method_with_self   
  3. irb(main):003:2> end  
  4. irb(main):004:1> end  
  5. => nil  
  6. irb(main):005:0> class A   
  7. irb(main):006:1> include M   
  8. irb(main):007:1> end  
  9. => A   
  10. irb(main):008:0> A.methods - Class.methods   
  11. => [] #空的,你能想到为什么么?  

让我仔细看看,我们定义的方法呢?
ruby 代码
  1. irb(main):009:0> M.singleton_methods   
  2. => ["method_with_self"]  #原来跑到M的单例类里面去了,别忘了,module也是Class  
好了,上面是include,那么,extend会发生什么情况呢?
ruby 代码
  1. irb(main):010:0> class B   
  2. irb(main):011:1> end  
  3. => nil  
  4. irb(main):012:0> B.extend M   
  5. => B   
  6. irb(main):013:0> B.ancestors   
  7. => [B, Object, Kernel]  

ok,再来让我们看看B的单例类此时发生了什么变化
ruby 代码
  1. irb(main):014:0> singleton_class_of_b = class<<B;self;end  
  2. => #<Class:B>   
  3. irb(main):015:0> singleton_class_of_b.ancestors   
  4. => [M, ClassModuleObject, Kernel]  #正如我们预料的,M变成了B单例类的直接父类  


正如预料的,M变成了B单例类的直接父类,M中定义的实例方法,变成了B的类方法(因为M中的实例方法被B的单件类继承,变成了单件类的实例方法,也就是B的类方法),M中定义的以self开头的类方法呢?当然仍然在M的单件类里面啦,它是不会随着M插入点的变化而变化的。

第二个破坏性实验,单件类中的self.xxx方法?

ruby 代码
  1. irb(main):001:0> class A   
  2. irb(main):002:1> end  
  3. => nil  
  4. irb(main):003:0> class<<A   
  5. irb(main):004:1> def self.method_defined_in_singleton_class_of_a   
  6. irb(main):005:2> end  
  7. irb(main):006:1> end  
  8. => nil  
  9. irb(main):007:0> A.singleton_methods   
  10. => []  #看来定义的singleton方法并不属于A   
  11. irb(main):008:0> singleton_class_of_a = class<<A;self;end  
  12. => #<Class:A> #A的单件类   
  13. irb(main):009:0> singleton_class_of_a.singleton_methods   
  14. => ["method_defined_in_singleton_class_of_a""new""nesting"]   
  15. #原来变成了A的单件类的singleton方法  


看了上面代码后想想其实很自然,我们之前说过“所有的类方法都是放在这个类对象的单例类中”,所以,我们新建的这个方法method_defined_in_singleton_class_of_a实际上是放到了A的singleton class <A>的singleton class<A<A>>中的。

第三个破坏性实验,找不到直接父类M?

ruby 代码
  1. irb(main):001:0> module M   
  2. irb(main):002:1> def self.class_method_defined_in_m   
  3. irb(main):003:2> puts "singleton method in m"  
  4. irb(main):004:2> end  
  5. irb(main):005:1> end  
  6. => nil  
  7. irb(main):006:0> class A   
  8. irb(main):007:1> include M   
  9. irb(main):008:1> end  
  10. => A   
  11. irb(main):009:0> A.ancestors   
  12. => [A, M, Object, Kernel]   
  13. irb(main):010:0> A.superclass   
  14. => Object  
上面irb结果可以看到,从继承树上来看A的直接父类是M,但是当我们调用A.superclass的时候却跳过了这个M,为什么呢?正如之前所说,我们在继承树上看到的M,其实只是M的一个代理,他的作用仅仅是用来做方法查找,让A变成一个代理类的子类,是没有意义的,所以,虽然实际上A确实称为了代理类的子类,但是从逻辑上讲,它的继承关系并没有被改变,它从逻辑上仍然是Object的直接子类
分享到:
评论

相关推荐

    Java实例化一个抽象类对象的方法教程

    总的来说,虽然Java中的抽象类不能直接实例化,但我们可以通过继承并实现其抽象方法,或者利用字节码工具和注解处理器在运行时或编译时动态生成新的类来间接达到实例化抽象类的目的。这样的设计允许我们创建更加灵活...

    android 仿京东商品三级分类简单实例

    在Android开发中,构建一个类似京东商品的三级分类系统是一项常见的任务,这涉及到用户界面设计、数据结构管理和触摸事件处理等多个方面。在这个简单的实例中,我们将探讨如何在Android平台上实现这样的功能,不涉及...

    Python实例方法、类方法、静态方法区别详解

    在Python编程语言中,方法是与类相关的函数,它们根据其用途和定义方式分为三类:实例方法、类方法和静态方法。这三种方法各有特点,适用于不同的场景。接下来,我们将详细介绍这三种方法的特点以及它们之间的区别。...

    浅谈python中的实例方法、类方法和静态方法

    Python中的实例方法、类方法和静态方法是面向对象编程中的核心概念,它们各自有不同的作用和使用场景。在Python中,这三个方法类型可以帮助我们更好地组织和管理类的行为。 1. **实例方法**: - 实例方法是与类的...

    Object语言基础之类的创建与实例以及方法的创建和调用

    原文地址:[Object-C语言随笔之三] 类的创建和实例化以及函数的添加和调用!http://blog.csdn.net/xiaominghimi/archive/2011/06/30/6577412.aspx

    Python实例方法、类方法、静态方法的区别与作用详解

    Python中至少有三种比较常见的方法类型,即实例方法,类方法、静态方法。它们是如何定义的呢?如何调用的呢?它们又有何区别和作用呢?且看下文。 首先,这三种方法都定义在类中。下面我先简单说一下怎么定义和调用...

    JAVA抽象类和抽象方法(abstract)实例分析

    三、抽象类和抽象方法的使用技巧 抽象类和抽象方法的使用技巧主要有以下几点: * 抽象类可以被继承,子类可以实现抽象类中的抽象方法。 * 抽象方法不能有方法主体,必须在子类中实现。 * 抽象类不能被实例化,因为...

    华为企业架构设计方法及实例 P105.pptx

    华为企业架构设计方法及实例 本文档主要介绍了华为企业架构设计方法及实例,涵盖了企业架构设计方法、企业架构内容框架、业务架构、数据架构、应用架构、技术架构等方面的知识点。 一、企业架构设计方法 企业架构...

    ASP.NET三层架构实例

    对于GustBook实例,DAL可能包含用于连接到SQL2000数据库、执行增删改查操作的类和方法。 实现这个三层架构,你需要以下步骤: 1. 创建数据库:使用VS2010内置的数据库工具,如SQL Server Management Studio,创建...

    类变量和实例变量.txt

    在面向对象编程中,尤其是在Java这样的语言里,类变量(也称为静态变量)和实例变量是两个重要的概念。它们都存储了对象的状态信息,但有着本质的区别。 - **实例变量**:实例变量是在每个对象创建时为其分配内存...

    java 通过反射获取枚举类,及枚举类的值,枚举类枚举实例名

    这些代码可能包括创建枚举类,然后通过反射获取枚举值、实例名以及演示如何使用`getDeclaredConstructor()`和`newInstance()`方法来访问私有构造函数(虽然这不是常规用法)。 通过深入理解这些概念,你可以更好地...

    java类与对象实例

    类与类之间的关系有依赖、组合和继承三种。依赖关系是指两个类之间的使用关系,组合关系是指一个类包含另外一个类,继承关系是指一个类继承另外一个类的属性和方法。 在 Java 中,类可以分为预定义类和自定义类。...

    通过类名获取类的实例对象

    反射允许程序在运行时检查自身结构,包括类、方法和属性等,从而实现动态类型操作。在Java中,反射是通过`Class`类和相关的API来实现的,而在C++中,由于标准库并不直接支持反射,我们需要借助一些第三方库或者...

    医学图像三维重建和可视化 VC++实现实例 代码包

    总的来说,《医学图像三维重建和可视化——VC++实现实例》这本书深入浅出地介绍了医学图像处理的关键技术和实现方法,配合代码包中的实例,读者可以深入理解并掌握这一领域的核心技能,为医学研究和临床诊断提供有力...

    java实验:请设计一个软件包。要求该软件包至少拥有三角形类、正方形类、圆类和正五边形类。每个类都要具有构造方法,而且可以构造任意的一般图形。

    要求每个类都含有计算该图形的周长的成员方法和计算的面积的成员方法。然后编写一个程序,分别创建这些类的实例对像,并输出这些实例对像的周长和面积。在创建这些实例对象时,构造方法的调用参数值可以自行设计!

    python类的实例化问题解决

    错误`TypeError: __init__() missing 1 required positional argument: 'h'`表明在尝试实例化`Speaker`类时,只提供了三个参数,而`__init__()`方法需要四个。这可能是由于忘记提供'hobby'参数,或者参数的顺序不...

    PYTHON学习教程资源:实例属性和类属性代码.docx

    本文将详细介绍实例属性和类属性的概念、使用方法和注意事项。 一、实例属性 在 Python 中,每个实例都可以有其自己的属性,这些属性称为实例属性。实例属性可以通过实例变量或 self 变量进行绑定。例如: ``` ...

    C# 简单的三层架构实例

    压缩包中的文件很可能是这个三层架构的实现代码,包括C#的类文件,可能包含表现层的接口和实现、业务逻辑层的类以及数据访问层的Linq查询。通过对这些文件的详细研究,我们可以学习如何在C#中构建和使用三层架构,...

    php创建类并调用的实例方法

    综上所述,创建类并调用实例方法的过程涵盖了类的定义、属性和方法的声明、对象的实例化以及通过对象实例来调用方法。掌握这些知识点是学习PHP面向对象编程的基础。通过这些技术的运用,可以创建出结构清晰、功能...

    PHP经典实例--类和对象

    总结起来,"PHP经典实例--类和对象"涵盖了从基本的类定义到高级特性,如魔术方法、解构器、访问控制和反射的全面内容。通过理解和实践这些概念,开发者能够更好地驾驭PHP的面向对象编程,写出更富有表现力、易于维护...

Global site tag (gtag.js) - Google Analytics