---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------
一、封装
封装指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。对一个类或对象实现良好的封装,可以实现以下目的:
1、隐藏类的实现细节。
2、让使用者只能通过事先预定的方法来访问数据,从而可以在该方法里加入控制逻辑,限制对属性的不合理访问。
3、可进行数据检查,从而有利于保证对象信息的完整性。
4、便于修改,提高代码的可维护性。
实现封装,要用到private关键字,如下程序所示:
class Person{
private String name;
private int age;
public void setName(String name){
if(name.length()>6||name.length()<2){
System.out.println("您设置的任命不符合要求");
return ;
}else{
this.name = name;
}
}
public String getName(){
return this.name ;
}
public void setAge(int age){
if(age>100||age<0){
System.out.println("您设置的年龄不合法");
return ;
}else{
this.age = age ;
}
}
public int getAge(){
return this.age ;
}
}
public class PersonTest {
public static void main(String args[]){
Person p = new Person();
//直接访问p变量的name属性,将出现错误
//p.age = 1000;
p.setAge(1000);//将会提示年龄设置不合法
System.out.println("未设置age属性时" + p.getAge());
//成功设置age属性
p.setAge(30);
System.out.println("成功设置age属性" + p.getAge());
p.setName("齐天大圣");
System.out.println("成功设置name属性:" + p.getName());
}
}
如上程序只能通过各自对应的setter方法来操作name和age属性值。因为使用setter方法来操作name和age两个属性,就允许程序员在setter方法中增加自己的控制逻辑,从而保证这两个属性不会出现与实际情况不符的情形。
二、继承
继承是实现软件复用的重要手段。Java的继承具有单继承的特点,即每个子类只有一个直接父类。Java的继承通过extends关键字来实现,实现继承的类称为子类,被继承的类称为父类。父类和子类的关系,是一种一般和特殊的关系。如水果和苹果的关系,苹果继承了水果,苹果是水果的子类。
Java里子类继承父类的语法格式如下:
修饰符 class SubClass extends SuperClass{
//类定义部分
}
下面程序示范了子类继承父类的特点。
class Friut{
public double wight;
public void info(){
System.out.println("我是一个水果!重" + wight+"g");
}
}
public class Apple extends Friut {
public static void main(String srgs[]){
//创建Apple对象
Apple a = new Apple();
//Apple对象本身并没有weight属性,但其父类有weight属性,因此也可以访问Apple对象的属性
a.wight = 50;
//调用Apple对象的info方法
a.info();
}
}
上面的Apple类本来只是一个空类,它包含了一个main方法,但是它继承了Friut类,因此在创建Apple对象之后,可以访问该Apple对象的weight实例属性和info()方法,这就表明Apple对象也具有了weight属性和info()方法,这就是继承的作用。
三、多态
Java引用变量有两种类型,一个是编译时类型,一个是运行时类型。其中编译时类型由声明该变量时使用的类型决定,运行时类型有实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就可能出现所谓的多态。示例程序如下:
class FatherClass{
//父类的book属性
public int book = 3;
public void show(){
System.out.println("父类的普通show方法:");
}
public void test(){
System.out.println("父类的将被覆盖的test方法:");
}
}
public class SonClass extends FatherClass {
//重新定义一个book实例属性隐藏父类的book实例属性
public String book = "同一个世界,同一个梦想!";
public void test(){
System.out.println("子类的覆盖父类的test方法");
}
public void son(){
System.out.println("子类的普通son方法");
}
public static void main(String args[]){
//下面编译是类型和运行时类型完全一样,因此不存在多态
FatherClass fa = new FatherClass();
System.out.println(fa.book);//输出3
//下面两次调用将执行SonClass的方法
fa.show();
fa.test();
//下面编译时类型和运行时类型完全一样,因此不存在多态
SonClass sc = new SonClass();
System.out.println(sc.book);
//下面调用将执行从父类继承到的show方法
sc.show();
//下面调用将执行当前类的test方法
sc.test();
//下面编译时类型和运行时类型不一样,多态发生
FatherClass FC = new SonClass();
//输出3,表明访问的是父类属性
System.out.println(FC.book);
//下面调用将执行从父类继承到的show方法
FC.show();
//下面调用将执行当前类的test方法
FC.test();
//因为FC的编译时类型是FatherClass,而FatherClass类没有提供son方法
//所以下面的代码编译时会出错
//FC.son();
}
}
上面程序的main方法中显示创建了三个引用变量,对于前面两个引用变量fa和sc,他们编译时类型和运行时类型完全相同,因此调用它们的属性和方法非常正常,完全没有任何问题。但是第三个引用变量FC则比较特殊,它的编译时类型是FatherClass,而运行时类型是SonClass类型,当调用该引用变量的test方法时(FatherClass类中定义了该方法,子类SonClass覆盖了父类的该方法)。实际执行的是SonClass类中覆盖后的test方法,这时多态就出现了。