Java语言作为一种面向对象的编程语言,其以功能强大和简单易用的特点,在IT领域一直占据着重要的地位。在这里将简单介绍一下Java语言的面向对象的特性
一、现实生活中的类和对象
现实世界中,万物皆对象。不管是你喝水用的杯子,写字用的笔,还是正在使用的电脑或手机,甚至是你自己,都是一个对象。
对象是你所看到的、想到的任何一个实体,它有形状、质量等基本属性特征,还具有计算(计算机),看博客(人)等功能或行为。它不是一类物品的统称,而是这个具体的物体。对这个物体抽象出来的特质,就是这个物体的属性,以及它的功能、行为。例如,一条狗就是一个对象,它的特征有:品种、颜色、名字等,行为有:叫、吃、跑等。
某一杯水,某一台电脑,某一个人是一个对象,那么水,电脑,人,就是这些对象,根据它们相似的属性特征、功能行为来分类得到的类别,用来描述这一类对象的特征或行为。现实生活中是找不到这么一个类的,能看到的都是对象。因此,现实生活中的类是抽象的,并不是具体的。
二、程序中的类与对象
程序中的类,就是根据现实生活中对象的特征和功能行为,按照程序中类的固定格式对其进行抽象定义。其中,public类的名字必须与文件的名字一致。程序中的类具有以下两个部分:
1.属性:属性就是根据对象的特征进行定义的,比如大小、形状等。在类的定义中,都是通过
访问修饰符 数据类型 数据名
对这个属性进行定义的。
如在一个奥特曼打小怪兽的游戏中,二者具有生命值和名字两个属性,因此对这个Role类的属性的定义如下:
public class Role{
int life;
String name;
}
属性的使用受到访问修饰符的限制。
2.方法:方法是根据对象的功能行为进行定义,分为构造方法和普通方法。
构造方法:构造方法是实例化对象时调用的方法,它的定义一般是:
访问修饰符 构造方法名(数据类型 参数名...)
其中需要注意的有以下几点:
1.构造方法名必须与类名一致,如果不一致则会报错。
2.构造方法是没有返回值的,在访问修饰符后紧跟的就是构造方法名,不能定义返回值类型,否则就是只是与类名相同的普通方法。
3.如果一个类中没有定义构造方法,Java会默认提供一个无参的构造方法。但如果类中写了构造方法,那么这个默认的无参方法将会被替换。
4.每次实例化一个对象时都会调用一次构造方法,因此一般将属性的初始化等放到构造函数中。
普通方法:普通方法的就是类对象的功能行为的定义,定义与一般函数的定义类似:
访问修饰符 返回值类型 普通方法名(数据类型 参数名...)
方法的调用同样受访问修饰符的控制。
因此,对于上面奥特曼打小怪兽的类,我们为它设置构造函数(用来初始化生命值和名字),和普通函数(一个用来表示攻击以及做出提示,另一个用来判断游戏是否可以结束)
public class Role{
int life; //生命值
String name; //名字
public int getLife() //获取生命值
{
return life;
}
public void setLife(int life) //设置生命值
{
this.life = life;
}
public String getName() //获取名字
{
return name;
}
public void setName(String name) //设置名字
{
this.name = name;
}
public Role(int life,String name) //带参构造函数
{
this.life=life;
this.name=name;
}
public void attack(Role ato) //设置攻击函数
{
System.out.println(this.getName()+"攻击了"+ato.getName());
ato.life--;
System.out.println(this.getName()+"的生命值为"+this.getLife());
System.out.println(ato.getName()+"的生命值为"+ato.getLife());
}
public boolean isDie() //判断另一方是否获胜
{
if(this.getLife()==0)
return true;
else return false;
}
}
那么,类的基本定义就是这些,它实例化对象的步骤如下:
类名 对象名 = new 构造方法名(参数...)
其中对类中属性和方法的调用都可以用:
对象名.属性名
对象名.方法名(参数...)
我们发现上面的构造函数和set函数中出现了this关键字,这个关键字是用来表示当前调用这个方法的对象。比如实例化Role的对象role,那么使用role.set...时,this就指代role对象,可以通过这一点,将对象的值进行初始化。
因此实例化两个不同的对象进行攻击,直到某一方生命值为0时结束游戏,其main函数如下
public static void main(String[] args) {
Role ato=new Role(5, "奥特曼"); //实例化奥特曼对象
Role monster=new Role(3, "怪兽"); //实例化怪兽对象
while(true)
{
ato.attack(monster);
if(monster.isDie())
{
System.out.println(ato.getName()+"胜利了!");
break;
}
monster.attack(ato);
if(ato.isDie())
{
System.out.println(monster.getName()+"胜利了!");
break;
}
}
}
输出结果如下:
三、类的继承
类的继承是面向对象中最重要的一个特征,它是从已有类中派生出新的类,新的类能够吸收已有类的数据属性和行为,并且能设置自己的新的属性和行为。类的继承能够节省大量的代码量(大多数重复的代码已经在它的父类中写过了),还能够增加程序的可扩展性(可以在已有程序的基础上增加新的属性和功能)。因此,掌握继承对学习面向对象编程十分重要。
在java中,类的继承是单继承,也就是一个类只能继承一个父类,
以上面那个奥特曼打怪兽作为例子,如果我们想让奥特曼和怪兽拥有除了生命值和名字外不同的属性,比如奥特曼具有变身时间这个属性,这时就不能够将这两个对象由同一个Role类实例化了。而是需要建一个奥特曼的Ato类和怪兽的Monster类,让他们继承Role类,再定义自己的属性和行为。那么,子类能继承到父类的哪些内容呢?
1.子类能继承到父类的所有非私有属性和普通方法。构造方法不能被继承,需要在子类中写自己的构造方法。值得一提的是,如果父类中没有无参构造函数,那么子类中需要重写自己的构造函数,此时编译器不会产生默认的构造函数。
2.访问修饰符控制属性和方法的使用范围。
因此可以定义一个Ato类:
package classex;
public class Ato extends Role{
int lasttime; //奥特曼变身的持续时间
public Ato(int life,String name)
{
this.life=life;
this.name=name;
}
}
这个Ato类继承了Role里的所有成员和普通函数,并定义了自己的构造函数,在新的奥特曼打小怪兽的游戏中,就可以实例化各自的对象来完成对战啦~
四、方法重载与重写
方法的重载与重写都是类中方法的一些使用,在这里单独列出来介绍,以使文章能够比较完善。
方法重载
方法重载在很多地方都见过,无非就是三类情况
1.方法参数的个数不同;
2.方法参数个数相同,但数据类型至少有一个不同;
3.方法参数的个数、数据类型都相同,但参数的顺序不同
只有满足这三个条件,才是方法重载。同样,调用时通过参数的个数、数据类型和顺序,比如手机的短信功能,从一开始只有文本这一个参数,到后来添加了表情这个参数,参数的个数发生改变,构成了重载。
方法重写:
重写就相当于覆盖,这个只能发生在有继承关系的子类中,它的要求如下
1.子类方法的名称、参数列表、返回类型与父类的方法完全一致;
2.子类方法的访问权限不能比父类低,即如果父类是public类型,子类的重写的方法也必须是public类型;
3.重写方法的方法体要不同。
至于实例化对象后,调用的是哪个类的方法,这个就涉及到多态的概念(父类引用可以指向子类对象)
如
Dialog d = new FrontDialog();
d.show(); //Dialog是FontDialog的父类
①若父类中有show方法,子类中也有show方法,则此时调用的是子类的show方法;
②若父类中有show方法,子类中没有show方法,则此时调用父类的show方法;
③若父类中没有show方法,子类中有show方法,则会报错。
五、抽象类与接口
1)抽象类
含有抽象函数的类叫抽象类,抽象类必须用abstract修饰,其定义如下
访问修饰符 abstract class 类名
{
访问修饰符 abstract 返回类型 函数名();
}
抽象类是不能被实例化的,因为它的抽象函数需要被重写。抽象函数可以被继承,继承的子类必须重写抽象函数,除非这个子类也是抽象类。
当然,抽象类中也可以有普通方法,但这样写意义不大,因此不多加赘述。
2)接口
接口算是抽象函数的更特殊形式,它的所有函数都是抽象的,所有数据成员都是public类型,且都是静态不能被更改。
其定义的过程如下:
public Interface 接口名 extends 接口
{
//定义常量
public static final 数据类型 常量名 = 值;
//定义抽象方法
public abstract 返回类型 方法名(数据类型 参数名...);
}
定义接口时能够继承其他多个接口,但只能用extends关键字,而不是实现接口的implements关键字。普通类实现接口时,只需要用 implements 接口名 即可,一个类可以实现多个接口,但只能继承一个类。
必须先继承,后实现接口,如
public class pip extends Role implements A,B,...{}
最后,关于this,super,多态等的详细介绍,将在之后慢慢推出...