Java与面向对象概述
来源:互联网 发布:java绘制动态图形 编辑:程序博客网 时间:2024/05/19 11:35
什么叫面向对象(Object Oriented,简称OO)?
你知道了JAVA虚拟机、编写了那么多的代码、也知道怎么编译、运行JAVA代码了,如果就到此为止,你就还没有窥探到JAVA的门道!换句话来讲,还没开始学习JAVA!
因为JAVA是面向对象的编程语言(OOP:Object-oriented Programming),我们到现在为止,还没有怎么接触面向对象的概念,所以,就等于还没开始学习JAVA!
顾名思义,所谓面向对象,就是一切以对象为核心!不管是面向过程,还是面向对象,都是为了解决问题而存在的一种思维方式!就是怎么样去理解和解决一个问题。世间万物皆对象。我们理解一个新的概念通常用类比的方法。现在我使用一个类比物:电脑。现在这里,每个人一台电脑,电脑就是一个对象。这台电脑是我用的,那台电脑是你用的,另外一台电脑是他用的……我的、你的、他的电脑看起来都一样,都有显示器、主机、键盘等等组成,我们都可以用它来工作、学习,这些同一种类型(type)的东西都叫电脑,这可以称为“电脑类”。类就是某种东西的类型。可以将类,看成是对象的蓝图。电脑类这个蓝图应该描述电脑的基本构成组件:显示器、键盘、鼠标、CPU、内存、主板、光驱等等,电脑类这个蓝图也应该描述它应该具备的基本功能:开机、关机、打字等等。换句话来说,类应该描述该类的对象所应包含的状态(state)信息和它们将能支持的行为(behavior)。
在面向对象的世界里,状态和行为结合成类的定义。这个定义用于作为创建对象的蓝图。电脑生产商根据电脑的规格描述生产电脑。也就是根据类创建对象。类的状态信息,也称为属性(attribute),比如:显示器、键盘、鼠标、CPU等等;类的行为称为操作(operation),比如:开机、关机、打字等等。
属性与操作,是描述一个类的最重要的内容。在JAVA中,操作也称为方法(method)。
那么我们需要定义一个什么样的类,或如何定义一个类呢?换句话来讲,就是我要定义的类,应该包括哪些属性和操作呢?这将涉及到一个概念:抽象
抽象
我们把抽象看成一个动词!所谓抽象,就是把现实世界中的事物用类来根据语境和需要进行描述。比如我的电脑CPU风扇运转不正常了,你的电脑光驱弹出有问题,这些内容,在电脑这个类中是否需要描述呢?对于生产电脑的系统来说,它可以不关心这些无需关心的细节;但是对于修理电脑的系统来说,这是必不可少的细节!这就是语境。
再比如说:我现在要开发一个学生信息管理系统,入学的时候,要把学生的信息录入,这时候,我关心学生的姓名、性别、专业、班级、民族、学生卡号等等,那么至于学生头发的颜色、穿什么衣服、有多少钱等等这些我们就不关心了。这就是关注该关注的,而忽略不重要的,无需关注的信息。
对现实进行抽象,这是我们在用面向对象的思维去开发软件的时候,要面对的一项真正的挑战!可以说,我们后面要开发的每一个项目,你都要进行相应的思维训练!训练你的抽象能力。
思维训练:
我手上拿着一根香烟:这根香烟就是“香烟”这个类的一个对象
一个班上有45个学生:那45个学生就是“学生”这个类的45个对象
大街上跑着3辆汽车:那3辆汽车就是“汽车”这个类的3个对象
继承
下面我们来学习面向对象三大特征(继承、封装、多态)之一的“继承”。世间万物皆对象,我们需要对这些对象进行归类,在归类过程中,我们发现有很多类型之间具有相同的特征。比如你家里养了一只猫,你家的那只猫可以称为“猫”这个类的一个对象;我家养了一条狗,我家的这条狗是“狗”这个类的一个对象;他家养了一只鸟,他家的这只鸟是“鸟”这个类的一个对象……那么,我们发现,猫、狗、鸟,都可以用同一个名称“动物”来称呼它!换句话来说,猫、狗、鸟都是一种动物!用面向对象的话来说,猫、狗、鸟这三个类“继承”了“动物”这个类。“动物”在这个关系中称为“父类/超类(super class)/基类”;猫、狗、鸟这三个类称为“子类(sub class)”。
在比如,上面说的电脑,台式机和笔记本都是电脑,笔记本如果按照厂商来分又可分IBM笔记本、HP笔记本、戴尔笔记本等等,当然,对于台式机也一样可以按照这种方式来划分,要不要这样划分,要看实际需要的情况。所以,IBM笔记本、戴尔笔记本是笔记本这个父类的子类,笔记本、台式机又是电脑这个父类的子类。
继承这个概念的目的之一是为了减少类定义的重复。电脑有显示器、键盘、鼠标、CPU、硬盘、内存这些属性和开机、关机、打字这些操作;那么,如果笔记本和台式机是电脑的子类,我们在定义笔记本和台式机的时候,就无需重复定义这些属性和操作了。
头脑风暴-思维训练:
请举出更多现实生活中存在继承关系的例子!
封装
封装(encapsulation)也是面向对象三大特征之一。这是面向对象中最重要的内容。对于台式机来讲,用一个机箱将主板、CPU、硬盘、内存这些零件包装(封装)起来,然后将鼠标、键盘、显示器这些东西开放出来让外界的人去操作。这就是关于封装的概念。电脑把一些重要的组件封装起来,避免外界的人对这些组件误操作而导致电脑异常(比如不小心把硬盘弄掉了);同时,电脑也需要暴露一些接口给外界操作。通过封装/隐藏重要的细节,同时暴露给外界一些操作的接口,外界的事物便能够和谐地和这些对象共处!
那么,接下来的问题就是:我们如何决定一个类该隐藏哪些属性或操作,该暴露哪些属性和操作呢?这些问题,就是面向对象的分析和设计中该回答的问题!需要根据具体情况来决定。我们后面的很多项目,也是要训练大家的这种思维的!
可见性
还是拿电脑来举例。比如我现在要用电脑的光驱来读一些光盘。我们通过电脑暴露给我们的接口(一个按键),我们按一下光驱的弹出按键,电脑内部就进行了一系列的动作,驱动电机的运转,把光驱弹出。这个弹出的过程,我根本不关心它是怎么弹出的,也不想关心它。所以,电脑就不应该将这个弹出的细节暴露出来!如果暴露出来了,可能会导致更大的问题,比如手动转动一个电机,不小心用力过猛把它弄坏了!如果把细节暴露出来,也导致了我们使用电脑的复杂度!电机本身(电脑的属性)以及驱动电机运行(电脑的操作)这些东西对外界隐藏起来了,称为私有(private)属性和私有操作。电脑提供了一个我们可以执行的“弹出光驱”操作,这个操作称为公有(public)操作。当然,比如键盘、显示器这些电脑的部件也暴露给我们了,可以称它们为公有(public)属性。
private、public就是可见性。可见性还包括protected和package可见性。只有电脑自身可以对象硬盘、内存、光驱这些private部件进行操作,也就是对电脑自身可见。换句话来说,具有private可见性的属性和操作,只有在类内部才可以访问。而具有public可见性的属性和操作,在任何地方(也就是其它任何对象)都可以访问。在类中声明为protected的元素,它的可见性程度介于private和public之间,可以被类内部的其它方法或类的所有子类(包括子类的子类)的方法访问。而如果在一个类中声明一个元素为package可见性,那么它能够被类自身和这个类所在的包(package)中的其它类访问。
现在我们来看看如何创建一个类,并定义它的属性(在类的内部,方法的外部定义的变量)和方法:
public class Computer {
//私有属性
private String harddisk; //硬盘
//私有属性
private String memory; //内存
//公有属性
public String display; //显示器
//公有属性
public String keyboard; //键盘
//公有属性
public String mouse; //鼠标
//公有方法:弹出光驱
public void popupCDRom(){
//do something
}
//公有方法:弹入光驱
public String injectCDRom(String cd){
//在类的内部,才可以访问类内部的私有方法
String content = readCDContent(cd);
return content;
}
//私有方法:读取光盘的内容
private String readCDContent(String cd){
//do something else
return "光盘"+cd+"上的内容:Hello World!";
}
}
测试它的可见性:
public class ComputerTest {
public static void main(String[] args){
Computer computer1 = new Computer();
//在ComputerTest这个类中,可以访问Computer中的public属性
computer1.display = "液晶显示器";
//在ComputerTest这个类中,可以访问Computer中的public方法
computer1.popupCDRom();
String content = computer1.injectCDRom("《2012》");
System.out.println(content);
//下面这行代码将导致编译错误
computer1.memory = "521M内存";
//下面这行代码将导致编译错误
computer1.readCDContent("《2012》");
//只有把ComputerTest这个类和Computer类放在一个package下面,才可以访问
computer1.otherProperties = "其它属性";
}
}
public class Person {
private String name;
protected int age;
String address;
}
public class Teacher extends Person {
public void myNameIs(){
//编译错误
System.out.println(name);
}
public void myAgeIs(){
//age是protected,可以访问
System.out.println(age);
}
}
public class FemaleTeacher extends Teacher{
public void myAge(){
//age是protected,可以访问
System.out.println(age);
}
}
上面的name/address/age,是定义在类的内部,方法体的外部的属性,称为成员变量,也称为实例变量(instance variable)或对象的状态(state)或字段(field)。
如何调用一个方法?参数必须匹配!
思考:如果在一个类中声明一个元素为package可见性,那么它是否能够被这个类的子类访问?
其它术语
l 一个类的对象一般也称为类的实例(instance)
l 类的属性(attribute)和操作(方法,method)也称为类的成员。
l 总结起来,定义在类内部,方法外部的属性,可称为instance variable(实例变量)或attribute(属性或特性)或member variable(成员变量)或field(字段),实例变量和成员变量这两个术语比较常用。
l 当说到属性这个词的时候,要特别注意:我们通常混淆了attribute和property之间的区别,如果属性指的是property,那么它的意思是由getters/setters方法所确定的property。在类内部直接定义实例变量/成员变量/字段称为attribute(请参考下面说的普遍被接受的基本原则)
l 为什么使用get/set?主要的目的还是为了封装(隐藏具体的实现细节),举例:
public class MyDateNoWrap {
public int year;
public int month;
public int day;
}
public class MyDateNoWrapClient {
/**
* @param args
*/
public static void main(String[] args) {
MyDateNoWrap mdnw = new MyDateNoWrap();
//把内部结构暴露给了外界,在赋值时,数据无法得到有效控制
mdnw.year = 2009;
mdnw.month = 15; //?? 导致类内部的数据不受控制!
mdnw.day = 1;
//把内部结构暴露给了外界,在取值时,给客户端制造麻烦
//客户端必需知道这个结构,才能得到正确的值
String theday = mdnw.year + "-" + mdnw.month + "-" + mdnw.day;
System.out.println(theday);
}
}
package cn.com.leadfar;
public class MyDate {
private int year;
private int month;
private int day;
public String getTheDay(){
return year + "-" + month + "-" + day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
if(month < 1 || month > 12){
throw new RuntimeException("您设置的月份数据有误!");
}
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
if(month <1 || month > 31){
throw new RuntimeException("您设置的日期数据有误!");
}
this.day = day;
}
}
package cn.com.leadfar;
public class MyDateClient {
public static void main(String[] args) {
MyDate md = new MyDate();
md.setYear(2009);
md.setMonth(12);
md.setDay(20);
System.out.println(md.getTheDay());
}
}
普遍被接受的基本原则
1、 属性应该被定义为private,除非在类继承结构中你需要把一个属性开放给你的子类使用(这时使用protected)。极少极少的情况,才需要定义为public。
2、 如果要将一个类内部的私有属性暴露给外界使用,通常不是将其定义为public,而是在类中针对这个属性创建get和set方法。get和set方法后面紧跟属性的名称,且第一个字母大写。
public class Person {
private String name;
private int age;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
上述类定义,定义了name/age/address这三个实例变量,同时,这个类,也定义了name/age/address这三个property
3、如果在一个类中,定义了get或set方法,那么通常称它为属性(property),这区别于类中的成员变量的名称。
public class Person {
private String _name;
private int _age;
private String _address;
public String getName() {
return _name;
}
public void setName(String name) {
this._name = name;
}
public int getAge() {
return _age;
}
public void setAge(int age) {
this._age = age;
}
public String getAddress() {
return _address;
}
public void setAddress(String address) {
this._address = address;
}
}
比如上面这段代码,_name、_age、_address称为Person这个类的成员变量(或实例变量或字段或attribute),而name、age、address称为Person这个类的property。大家看:
getName()/setName这两个方法,以get/set开头,紧跟Name这个名称,N大写,这是习惯写法,而且大家也应该这样写(N这个字母不要写小写!),这种写法,就确定了名为name(注意是n而不是N)的property。
这些get/set方法,称为getters/setters。
如果一个property有get方法,称这个property是readable(可读的)的
如果一个property有set方法,称这个property是writable或modifiable(可写的)的
如果一个property只有get方法,称这个propety是readOnly(只读)
如果一个property只有set方法,称这个property是writeOnly(只写)
- Java与面向对象概述
- Java与面向对象概述
- Java与面向对象概述
- Java面向对象概述
- Java面向对象概述
- Java面向对象概述
- JAVA面向对象概述
- Java对象与类——面向对象程序设计概述
- 【读书笔记】java语言与面向对象程序设计1:java概述
- 黑马程序员 Java基础<一>面向对象与类概述
- Java基础-->面向对象与类之概述
- Java面向对象编程概述
- Java面向对象编程概述
- java面向对象_概述
- java基础-面向对象概述
- Java面向对象(1)概述
- java回顾 --- 面向对象概述
- 黑马程序员——Java面向对象(一)—面向对象的概述、类与对象的关系、封装
- SDL Trados
- unique_copy使用
- 使用Ant编译大量java文件时出java.lang.OutOfMemoryError
- 数据库权限
- C#生成随机数,支持多种方式[类]
- Java与面向对象概述
- 微型机器人进入人体治疗疾病有望5年内实现
- Vim进阶
- XStream两分钟教程(译)
- bolg record
- 过滤器[登录+编码]filter在程序中的使用
- js为元素动态添加css代码
- 配置文件中appSetting和connectionStrings
- 如何在Windows XP中重新安装或修复IE6