9.18
第四章 一切都是对象
这个章节的例子都举得很浅显易懂,而且作者的语言= =噗,委实生动有趣啊是~~
4.1 两种思维方式
初期的编程思想是:以“如何做”为指导来编写代码。这时期的编程语言叫过程语言,提倡结构化地设计程序代码。代表语言是FORTRAN和C。
现在的编程思想是:以“谁将被影响”为指导来编写代码。叫面向对象的编程语言,以类为模块,以消息来驱动程序的执行。代表语言是C++ 和Java。
4.2 对象
(这里是文摘。。。。摘摘摘摘摘。。。。。)
每个事物都有一些特点,人有身高,体重,在程序中我们称之为属性;还可以有一些行为,人要吃饭,睡觉,在程序中我们称之为方法。
学生是人,自然有身高,体重,自然要吃饭,睡觉。如果你把人看作一类事物,把学生看作一类事物;那么,人是父类型,学生是子类型。子类型从父类型自然得到属性、方法,我们称之为继承。
学生要考试,工人不要;工人拿工资,学生不拿(一般而言)。同一个父类,不同的子类有不同的行为和状态,我们称之为多态。
人们编写程序,也就是在描述一类事物的特点(属性)、行为(方法)。有时候是模拟描述自然界中已有的一类事物,还有时候是创造地描述自然界中没有的一类事物。
当人们决定了代码世界中一类事物的属性、方法,在代码世界中,这类事物的属性、方法只有定义代码的人知道,其它的类是不知道的。这就是封装。
封装、继承、多态是面向对象编程的三个本质特征。
4.3 封装
让我们来定义一个类,类名是Person,类名首字母要大写;
属性有姓名@name、年龄@age、国籍@motherland,实例变量用@开头;
方法有一个,叫talk, 方法名和参数名应该用一个小写字母开头或者用一个下划线开头。
举个例子吧~
class Person
def initialize( name, age=18 ) #initialize是初始化方法,相当于Java的构造器。参数age有一个缺省值18,可以在任何方法内使用缺省参数,而不仅仅是initialize。
@name = name
@age = age
@motherland = "China"
end #初始化方法结束
def talk
puts "my name is "+@name+", age is "+@age.to_s #@age.to_s的含义是:将数@age转换为字符串。
if @motherland == "China"
puts "I am a Chinese."
else
puts "I am a foreigner."
end
end # talk方法结束
attr_writer :motherland #相当于def motherland=(value); return @motherland =value; end
end # Person类结束
p1=Person.new("kaichuan",20);p1.talk
p2=Person.new("Ben");p2.motherland="ABC";p2.talk
#my name is kaichuan, age is 20
I am a Chinese.
my name is Ben, age is 18
I am a foreigner.
4.4 继承
class Student < Person #用“ < ”表示Student类是 Person类的子类。
def talk #Student类继承Person类的一切,而这里Student类重写了talk方法。
puts "I am a student. my name is "+@name+", age is "+@age.to_s #子类继承父类的时候,除了重写方法;也可以添加一些新的方法;或是增强父类的方法(用关键字super指明)。
end # talk方法结束
end # Student类结束
p3=Student.new("kaichuan",25); p3.talk
p4=Student.new("Ben"); p4.talk
#I am a student. my name is kaichuan, age is 25
I am a student. my name is Ben, age is 18
注意:如果子类不重新定义方法的话,会默认该子类使用父类的方法。另,所有新增的类都是属于Ruby语言中已经定义了的Object类,如果你在定义新类的时候,没有指明新类的父类,那么,Ruby解释器认为,新类的父类是Object类。类Object含有new方法、initialize方法…只要你不重写这些方法,你就自然在使用类Object的方法。
说个好玩儿的,在这一节的后面有这样一段话,实在是有趣啊~哈哈哈哈哈~~~
“一个实例生成了,又一个实例生成了…他们或许是同类型的,或许不是同类型的,或许是有亲缘关系的。无数的实例在代码世界中交互、缠结,忽生忽死,无休无止…”
4.5 多态
多态在这里就不多说了,其实就是不同子类的多样性,基本来说,我的理解就是,他们定义的方法不同,或者是数目不同,或者是同一名称的方法的内容不同。
这里要注意的是,“Ruby语言,只有重写(override),没有其它语言具有的严格意义上的重载(overload)”。
9.26
第五章
5.3 详解变量—— 动态类型
在ruby当中,变量和方法区分的并不明显。变量要有的特性:#只抽出了需要的两点
1). 变量有名字;
2).变量代表的那个事物应该有一个可以用数学度量的值;长度,面积,速度大小,磁场强度…
在 Java 中,编译的时候,就完成了类型匹配的检测,这属于前期绑定; Ruby 是在运行中检测,检测类型匹配吗?不是检测类型匹配,而是检测语法,只要与语法定义不矛盾,就能通过。这样成就了方便,也造就了麻烦,如果变量的命名不清晰明了,就容易出现错误。“如何避免常常出错呢?有一个下口之处,就是死盯住变量的命名。用一些有意义的名字,不必太长,但是应该少用单字符,除非是循环指针变量。你也许认为我自己能看懂就行了,这是十分有害的想法。在一个项目组中,程序员是要彼此相互沟通合作的。当坏习惯养成后,要改是很难的。”
Ruby中“方法”的增删改#举例删除,修改也是同样,重新在类里定义方法就好
class Person
def talk
puts "Today is Saturday. "
end
end
p1=Person.new
p1.talk # Today is Saturday.
class Person
undef :talk
end #p1.talk talk方法已经不存在
5.5 一些编码建议
# 题外话,果然有txt就是好啊,清除格式什么的最好用了,从别的地方复制过来的文档总有些奇奇怪怪的格式,更坑爹的是还有可能影响到其它文本,所以粘贴过来前先放txt里面净化一遍真是太好了啊~~
一. 命名
常量全用大写的字母,用下划线分割单词。例如:MAX, ARRAY_LENGTH。
类名和模块名用大写字母开头的单词组合而成。例如:MyClass, Person。
方法名全用小写的字母,用下划线分割单词。例如:talk, is_prime?。在Ruby里,有时将“!”和“?”附于某些方法名后面。
惊叹号“!”暗示这个方法具有破坏性, 有可能会改变传入的参数。问号“?”表示这个方法是一个布尔方法,只会返回 true 或 false。
变量和参数用小写字母开头的单词组合而成。例如:name, currentValue。
类名、模块名、变量名、参数名最好使用“名词”或者“形容词+名词”。
方法名最好使用“动词”或者“动词+名词”。例如:aStudent.talk 。
二. 空格和圆括号
关键字之后要留空格。
逗号“,”、 分号“;”之后要留空格。 “,”、 “;”向前紧跟,紧跟处不留空格。
赋值操作符、比较操作符、算术操作符、逻辑操作符,如“=”、“+=” “>=”、“<=”、“+”、“*”、“%”、“&&”、“||”等二元操作符的前后应当加空格。
一元操作符如“!”、“~”等之后不加空格。
象“[]”、“.”、“::”这类操作符前后不加空格。
函数名之后不要留空格,紧跟左圆括号“(”,以与关键字区别。左圆括号“(”向后紧跟,右圆括号“)”向前紧跟,紧跟处不留空格。
#只要不会造成逻辑错误神马的,圆括号()基本可以省略。
三. 使用 return
你在定义方法的时候,在最后一行可以显式地 return 某个值或几个值,但却不是必须的。 Ruby 方法的最后一行语句如果是表达式,表达式的值会被自动返回;最后一行语句如果不是表达式,就什么也不返回。
第六章 深入面象对象
6.1 重载?重写
重载 4.5节说到:“ Ruby语言,只有重写,没有其它语言具有的严格意义上的重载。” 下面仔细分析 Ruby 为何没有重载,只有重写。
Ruby支持缺省参数,我们看程序 E6.1-1.rb : Ruby还支持可变参数,我们看程序 E6.1-2.rb : #由于缺省参数和可变参数,参数个数不同而产生的重载,在Ruby中不再有效。 |
重写
在子类和父类中,如果子类里不写该方法,那么就是直接集成父类;如果是子类重新写了该方法,那就是执行子类当中的方法。 写在同一个类中的不同方法,总是写在后面的方法被实现。 |
6.2 增强父类方法
之前一直搞不懂增强父类的方法是什么(喂喂,提前暴露自己学校没好好学了吧= =||),咳咳,原来意思是说,以子类身份执行方法时,除了执行父类方法,还会执行子类中该方法添加的部分。
class Person
def talk(name)
print "my name is #{name}."
end
end
class Student < Person
def talk(name)
super
print "and I'm a student.
"
end
end
aPerson=Person.new #只执行父类中输出姓名
aPerson.talk("kaichuan") #my name is kaichuan.
aStudent=Student.new #除了执行父类中的输出姓名,还执行子类中的super增强部分。
aStudent.talk("kaichuan") #my name is kaichuan.and I'm a student.
# 之前有想过,其实在子类中重写方法也是一样的嘛,而且更清晰。但是再一想,如果量啊逻辑啊神马的比较麻烦,那还是这样好了,更简单一些~~
6.3 实例变量、类变量、类方法
如果一个变量,其作用域遍及在程序的任何位置,这样的变量称之为全局变量;与之相对,作用域仅限于在程序的某一单元的变量,称之为局部变量。
如果一个变量,只能被某个实例对象使用,这样的变量称之为实例变量;如果一个变量,能被某个类的所有实例对象共享,这样的变量称之为类变量。
常量可以定义在类和模块中,不能定义在方法中(方法中只能对变量进行赋值,或者设置变量的缺省值。)。如果在外部访问类或模块中的常量,要使用域作用符:: 。 全局变量用$ 开头。 实例变量,变量名用@ 开头;类变量,变量名用@@ 开头. Ruby中所说的局部变量,可以是存在于类中、方法中、模块中、一个循环中、一个过程对象中。局部变量名用小写字母开头。 |
实例变量:譬如类Student,学生Jmy是一个实例,那么@name、@age、@motherland,都是实例变量,被每个实例独享。
类变量:譬如类Class0901,学生Jmy是一个实例,@@count(班级人数)是类变量,被class0901类里所有实例共享。
class StudentClass |
class StudentClass @@count=0 #调用一个类方法,与定义类方法一样,要在方法名前加上类名和一个点号“.”。类方法提供了一个途径,在类的外部访问类变量,无须通过类的实例方法。 #调用类方法,不需要依赖于任何实例的方法 |
10.08
6.4 单例方法
class Person
|
在Ruby里,可以给具体的实例对象添加实例方法,这个方法只属于这个实例对象,我们把这样的方法称之为单例方法。
定义单例方法,首先要生成一个实例对象;
其次,要在方法名前加上对象名和一个点号“.”。
左图程序中,对象p1不可以laugh , laugh方法只属于p2对象。
6.5 访问控制
控制对方法的访问,有三种方式:
Public 可以被任何实例对象调用,不存在访问控制;
Protected 可以被定义它的类和其子类访问,可以在类中或子类中指定给实例对象;
Private 可以被定义它的类和其子类访问,不能被实例对象调用。
Public 方法默认都是公有的( initialize方法除外,它永远是私有的)。
class Person p1=Person.new protected:speak,将调用laugh private:laugh p1.speak #protected method 'speak’ p1.laugh #prrivate method 'laugh’ |
class Person
|
class Person p1=Person.new def p1.speak puts"I am p1." end p2.useSpeak(p1) # I am p1. |