封装的概念还是很容易理解的。如果你会定义类,那么相信你对封装的概念已经完全掌握了。下面定义的几个类,就是对数据的封装。
继承的好处是代码复用。继承的子类自动拥有父类中的所有属性和方法。所以继承已存在的类就是复用这些类的方法和域。
在此基础上,子类还可以添加一些新的方法和域,以满足新的需求。这是Java程序设计中的一项核心技术。
那么如何判断是否需要继承呢?"is-a"关系是继承的一个明显特征。这句话的意思可以解释为:Student之所以继承Person,
是因为Student 是Person。如果没有这个关系也就不需要这个继承了。这也是里氏替换原则的定义,子类型必须能够替换掉它们的父类型。
在通过扩展超类定义子类的时候,仅需指出子类与超类的不同之处。因此在设计类时,应该将通用的方法放到超类中,
而将具有特殊用途的方法放到子类中,这种将通用的功能放到超类的做法,在面向对象程序设计中十分普遍。
动态绑定有一个非常重要的特性:无需对现存的代码进行修改,就可以对程序进行扩展。所以多态是开放封闭原则的基础。
下面是一个继承和多态实现的具体例子:
abstract 是抽象的关键字。(最好从抽象类继承而不是从具体类继承)。
public abstract class Person { // 抽象类 private String name; // 私有变量 public String getName() { // Getter方法 return name; } public void setName(String name) { //Setter方法 this.name = name; } public Person(String name) { // 构造函数,用于初始化name super(); this.name = name; } public abstract String getDesc(); // 抽象类中的抽象方法。 只有声明,没有具体实现。
public String toString(){ // toString方法覆盖了Object类的toString方法
return name + getDesc();
}
}
extends 是继承的关键字。Student继承Person,所以Student拥有name属性。
public class Student extends Person { // 继承类 private String major; // 新增加的数据 public String getMajor() { return major; } public void setMajor(String major) { this.major = major; } public Student(String name,String major) { // 构造函数用于初始化 super(name); // 调用超类构造函数 this.major = major; } @Override public String getDesc() { // 必须实现超类中的抽象方法 // TODO Auto-generated method stub return " : a student, major is " + major; }
凡是继承超类的子类,必须实现(无论是哪种实现方式)超类中定义的抽象方法。
public class Employee extends Person{ private double salary; public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public Employee(String name, double salary) { super(name); this.salary = salary; } @Override public String getDesc() { // TODO Auto-generated method stub return " :a employee, salary is " + salary; } }
一、定义
Java接口(Interface),是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
接口定义的一般形式为:
[访问控制符]interface <接口名> {
类型标识符final 符号常量名n = 常数;
返回值类型 方法名([参数列表]);
…
}
二、接口的特点
1、Java接口中的成员变量默认都是public,static,final类型的(都可省略),必须被显示初始化,即接口中的成员变量为常量(大写,单词之间用"_"分隔)
2、Java接口中的方法默认都是public,abstract类型的(都可省略),没有方法体,不能被实例化
3、Java接口中只能包含public,static,final类型的成员变量和public,abstract类型的成员方法
4、接口中没有构造方法,不能被实例化
5、一个接口不能实现(implements)另一个接口,但它可以继承多个其它的接口
6、Java接口必须通过类来实现它的抽象方法
7、当类实现了某个Java接口时,它必须实现接口中的所有抽象方法,否则这个类必须声明为抽象类
8、不允许创建接口的实例(实例化),但允许定义接口类型的引用变量,该引用变量引用实现了这个接口的类的实例
9、一个类只能继承一个直接的父类,但可以实现多个接口,间接的实现了多继承.
三、接口的用法
1、精简程序结构,免除重复定义
比如,有两个及上的的类拥有相同的方法,但是实现功能不一样,就可以定义一个接口,将这个方法提炼出来,在需要使用该方法的类中去实现,就免除了多个类定义系统方法的麻烦。
用来计算每一种交通工具运行1000公里所需的时间,已知每种交通工具的参数都是3个整数A、B、C的表达式。现有两种工具:
Car 和Plane,其中Car 的速度运算公式为:A*B/C
Plane 的速度运算公式为:A+B+C。
如果增加第3种交通工具的时候,比如火车(Train)不必修改以前的任何程序,只需要编写新的交通工具的程序。
import java.lang.*;
interface Common {
double runTimer(doublea, double b, double c);
String getName(); //获取交通工具的名称
}
class Plane implementsCommon {
public doublerunTimer(double a, double b, double c) {
return (a+ b + c);
}
public String getName(){
return"Plane";
}
}
class Car implements Common {
public doublerunTimer(double a, double b, double c) {
return ( a*b/c );
}
public String getName(){
return"Car";
}
}
public class ComputeTime {
public static void main(Stringargs[]) {
double A=3;
double B=5;
double C=6;
double v,t;
Common d=new Car();
v=d.runTimer(A,B,C);
t=1000/v;
System.out.println(d.getName()+"的平均速度: "+v+" km/h");
System.out.println(d.getName()+"的运行时间:"+t+" 小时");
d=newPlane();
v=d.runTimer(10,30,40);
t=1000/v;
System.out.println(d.getName()+"的平均速度: "+v+" km/h");
System.out.println(d.getName()+"的运行时间:"+t+" 小时");
}
}