下面使用的代码在这里 JavaStudy/HeadFirstJava/ClassAndObject可以下载。
这一部分形象生动的讲述了面向过程和面向对象的主要区别。
如下:
新增一个阿米巴形状的旋转和播放声音,并且旋转的中心点与其他形状的不一样。加上播放的声音文件格式也与其他的不一样。
也许还会有各种各样不同的需求
要是我单单看到需求(1),我也会像阿珠那样思维定式(面向过程),首先写两个函数:
// shapeNum标记不同形状
void rotate(int shapeNum);
void play_sound(int shapeNum);
程序中根据参数shapeNum来进行不同的旋转和播放声音。
当看到需求(2)时,我首先也是想到了增加两个函数的参数来进行控制。
// originPoint标记以哪个点进行旋转
void rotate(int shapeNum, int originPoint);
// file_flag标记播放哪种声音
void play_sound(int shapeNum, int file_flag);
这两个函数满足需求(2)是没问题的,但是问题在于之前根据需求(1)写好的函数现在要重写,费力。
不过,我偷偷的看了阿花写的面向对象程序的设计思路,我觉得我们采用面向过程也是可以写出来的。
// 四边形
void Square_rotate(int originPoint);
void Square_play_sound(int file_Flag);
// 圆形
void Circle_rotate(int originPoint);
void Circle_play_sound(int file_Flag);
// 三角形
void Triangle_rotate(int originPoint);
void Triangle_play_sound(int file_Flag);
// 阿米巴形
void Amoeba_rotate(int originPoint);
void Amoeba_play_sound(int file_Flag);
哈哈,这个是跟阿花的设计思路是差不多的。
但我觉得,可别指望着采用这种方式来写代码,因为后面有可能再出现其他的形状,并且这样写的代码重复量很多,即使你把重复的代码封装成一个函数,也不能保证这个函数到处都可以用。唉!突然觉得面向对象也蛮不错的
阿花针对需求(1)(2)的设计思路如下:
这样的设计思路很清晰,各个类没有多大的相互影响,即使需求再怎么变化,改动也非常的小。其中涉及到的父类、子类、覆盖等术语,后面的文章会给出详细的说明。此时我也不是很懂。
按照我的理解,在程序设计中,你首先要考虑到涉及到哪些东西,也就是对象。每个对象都是一个独立的个体。然后再这些对象中找出共性的地方,再产生一个更为抽象的对象。整个过程中,都是站在对象的角度上进行程序的设计。
类不是对象,却是用来创建它们的模型
下面这张图可以很明确的说出它们之间的差别。
上面这张图可以翻译成如下的代码:
// Contact.java文件
public class Contact{
// 实例变量
String Name;
String PhoneNum;
String eMail;
String Address;
// 方法
void SetName(String name)
{
Name = name;
}
String GetName()
{
return Name;
}
String GetAddress()
{
return Address;
}
String GetPhoneNum()
{
return PhoneNum;
}
}
// ContactTest.java文件
public class ContactTest{
public static void main(String[] args)
{
Contact Tom = new Contact(); // 创建两个对象
Contact Jerry = new Contact();
Tom.SetName("Tom"); // 对象的实例化
Jerry.SetName("Jerry");
System.out.println(Tom.GetName());
System.out.println(Jerry.GetName());
}
}
Contact是一个类,是一个空白的通讯录模板。在main()中,我们使用Contact类(这个模板)创建了两个对象Tom和Jerry。接下来是对象的实例化(把Tom和Jerry存储到通讯录中)。不知道我这样理解对不对。。。。
说实话,要是我以前不知道面向对象的,让我一个习惯于C语言的人来说,让我离开main()简直是不可能的一件事。面向对象中,用对象来与对象交互。
测试真正的类
启动Java程序
一旦我们创建对象,他会存放在堆上,该内存区域是可回收的。
上图中有如下几个疑问:
1、“不管对象如何创建都会放在此区域中”,难道对象有多种创建方式?
2、 分配的内存空间是根据什么来决定的呢?
3、“当某个对象被Java虚拟机觉察到不会再被使用到,该对象就会被标记成可回收的”,那么,什么时候对象才算是不会被使用到呢?那又怎么标记成可回收呢?
带着上述三个疑问,开始google。
//Dog为类名
Dog dog; // 方式1
Dog *p = new Dog(); // 方式2
方式1中,dog是被存储在栈中的,占用的大小是Dog类中成员变量占用内存的和;
方式2中,在定义*p时在栈中开辟一个4字节的空间,new Dog()时在堆中开辟一块空间,然后将该空间的首地址赋值给*p,这样,通过*p就可以找到对象在堆中的任何成员方法了。
Dog dog = new Dog(); // 方式3
JVM在进行内存管理时,首先会在栈中给dog分配一个空间,当new Dog();后会在堆中开辟对象的实际空间,然后将dog指向堆中的空间,这样我们就可以方法对象的成员变量了。
其中方式2和方式3很像,在C++中p是一个指针,通过指针我们可以访问内存中的任何地址,可以肆意的对内存做处理,然而在Java中 dog是一个引用,可以理解成是C++中指针的一个封装,我们不可以想在C++中用指针那样在Java中直接的进行地址++操作,这样一来就保证了内存的安全,这是C++和Java的很大不同。
上述资料都是参考这篇文章的。不过,改文章中方式1和方式2画的示意图反了,这点需要注意一下。
这篇文章有介绍,Mark先。
为对象分配的内存空间的大小是由类的成员变量占用内存的和来决定的。那么成员方法呢?
成员方法是存放在公共存储区以便所有该类的对象都可以访问的。
怎么理解这句话呢?以上面的Contact为例。因为每个对象是相互独立的(Tom和Jerry是独立的),也就是说大家的成员变量是相互独立的(Tom的Name、Address、PhoneNum肯定是跟Jerry的不一样),所以都需要为他们的成员变量分别开辟空间存储。但是成员方法是大家共有的,所以并不需要为每个对象开辟空间存储成员方法,而只需把成员方法放在公共存储区即可。
对象在什么时候被回收呢?好吧,看了这篇文章还是不太懂,先Mark一下。