接着java基础一继续介绍以下内容:
继承:
1.承的定义过程实际包括以下的几个过程
a. 子类继承父类中声明为public和protected的成员变量和成员方法,但不能继承被声明为private的成员变量和成员方法
b. 重写基类成员,包括数据成员和成员函数。如果子类声明了一个与父类成员函数相同的成员函数时,子类中的新成员则屏蔽父类同名成员,类似函数中局部变量屏蔽全局变量,成为同名函数的覆盖。
c. 定义新成员。新成员是子类自己的心特点。子类新成员的加入使得子类在功能上有所发展
d. 必须在子类中重写构造函数,因为构造函数不能被继承。
2.性的隐藏
所谓属性的隐藏是指子类拥有两个相同名字的变量,一个来自父类,一个自己定义;当子类执行继承自父类的操作时,处理的是继承自父类的变量,而当子类执行自己定义的方法时,所操作的就是他自己定义的变量,而把继承自父类的变量隐藏起来
以下为一个实例:
package zwq01;
//定义父类,学生类
public class Student {
String name;//姓名
int number;//学号
double point;//分数
static int cNumber = 101300;//存放学号
static double miniPoint = 60;//最低成绩
public Student(){
//无参构造函数
number = cNumber++;
}
public double getMiniPoint(){//获取最低成绩
return miniPoint;
}
}
package zwq01;
//创建学生类的子类,大学生类
public class Ustudent extends Student {
double sPoint;//学习成绩
static double miniPoint = 30;//平时成绩及最低成绩
public Ustudent(){
//子类的构造方法
}
public double getSPoint(){
return miniPoint;
}
}
package zwq01;
//测试类
public class Test {
public static void main(String[] args) {
Student st = new Student();//创建学生对象
System.out.println("学号为:"+st.number+"最低成绩为:"+st.miniPoint);
//调用父类的方法输出学生的最低成绩
System.out.println("学号为:"+st.number+"最低成绩为:"+st.getMiniPoint());
Ustudent us = new Ustudent();//创建一个大学生类的对象
System.out.println("学号为:"+us.number+"大学生最低成绩:"+us.miniPoint);
//调用子类的方法输出大学生的最低成绩
System.out.println("学号为:"+us.number+"大学生的最低成绩:"+us.getSPoint());
}
}
测试结果:
学号为:101300最低成绩为:60.0
学号为:101300最低成绩为:60.0
学号为:101301大学生最低成绩:30.0
学号为:101301大学生的最低成绩:30.0
3.在子类中使用构造方法
子类其实可以继承父类的构造函数,但只能继承父类中不含参数的构造函数。如果子类自己定义了构造函数,则在创建对象时,他将先执行继承自父类的无参构造函数,然后再执行自己的构造函数。
由于子类无法访问父类的私有数据成员,那么他必须通过一个构造函数来初始化父类的数据。这个构造函数通过使用super关键字来调用,但是这个语句必须是子类构造函数的第一个执行语句。
4.关于子类构造函数的使用总结:
a.子类构造函数总是先调用(显示或者隐式)其父类的构造函数,以创建和初始化子类的父类成员。
b.构造函数不能继承,他只属于定义他们的类
c.创建一个子类对象时,首先调用父类的构造函数,接着才行子类的构造函数
以下是一个子类中使用构造函数的实例
package zwq02;
//创建员工类的子类
public class CoEmployee extends Employee {
private double bonus;//奖金
public CoEmployee(){
//子类的构造方法
System.out.println("调用子类的构造函数!");
}
public CoEmployee(String name,double bonus){
super(name);//通过super()的调用,给父类的数据成员赋值
this.bonus = bonus;
System.out.println("调用子类的构造函数!!!");
}
public double getBonus(){//新增方法,获取奖金
return bonus;
}
public void setBonus(double nBonus){
bonus = nBonus;
}
//在子类中重新覆盖父类的方法
public double getTSalary(){
double salary = getMiniSalary();
return bonus + salary;
}
public String toString(){
String st;
st = super.toString();
//调用自身对象的getTSalary()方法
return(st);
}
}
package zwq02;
//父类员工类
public class Employee {
String name;//姓名
int number;//编号
String sex;//性别
private double tSalary;//总工资
static int cNumber = 101300;//存放编号
static double miniSalary= 600;//最低工资
public Employee(){
//无参构造函数
number = cNumber++;
System.out.println("调用父类的构造函数!");
}
public Employee(String name){
//有参构造函数
System.out.println("调用父类的构造函数!!");
number = cNumber++;
this.name = name;
}
public double getMiniSalary(){//获取最低工资
return miniSalary;
}
public int getNumber(){//获取编号
return number;
}
public double getTSalary(){//获取总工资
return tSalary;
}
public void setTSalary(double nSalary){//计算总工资
tSalary = nSalary+miniSalary;
}
public String toString(){//输出员工基本信息
String st;
st="编号:"+number+"姓名:"+name;
if(sex.compareTo("男")==0)
st = st+":性别:男";
else
st = st+":性别:女";
return(st+":工资");
}
}
package zwq02;
//测试类
public class Test {
public static void main(String[] args) {
Employee em = new Employee("张三");//创建员工对象
em.sex = "男";
em.setTSalary(1200);
System.out.println("员工基本信息为:"+em.toString()+em.getTSalary());
CoEmployee coem = new CoEmployee("李四",400);//创建子类员工对象
coem.sex = "女";
System.out.println("员工基本信息为:"+coem.toString()+coem.getTSalary());
}
}
测试结果:
调用父类的构造函数!!
员工基本信息为:编号:101300姓名:张三:性别:男:工资1800.0
调用父类的构造函数!!
调用子类的构造函数!!!
员工基本信息为:编号:101301姓名:李四:性别:女:工资1000.0
5.this关键字:用this关键字的三种情况
a.想通过构造方法将外部传入的参数赋值给类的成员变量,构造方法的形式参数名称与类的成员变量名相同。
class Person{
String name;
public Prson(tring name){
this.name=name;
}
}
b.假设有一个容器类和一个部件类,在容器类的某个方法中药创建部件类的实例对象,而部件类的构造方法要接受一个代表其所在容器的参数。
class Container{
Component com;
public void addComponent(){
com = new Component(this);
}
}
class Component{
Container myContainer;
public Component(Container c){
myContainer=c;
}
}
c.可以在一个构造方法中调用其他重载的构造方法,不是用构造方法名,而是用this(参数列表)的形式,根据其中的参数列表,选择相应的构造方法
public class Person{
String name;
int age;
public Person(String name){
this.name=name;
}
public Person(String name,int age){
this(name);
this.age=age;
}
}
6.super关键字:表示的是当前对象的直接父类对象,是对当前对象的直接父类对象的引用。
a.调用父类的构造函数
public Com(String name,double point){
super(name);
this.point=point;
}
这里的代码super(name)的意思是调用父类的构造函数给父类的数据成员赋初值。
b.调用父类的方法
如前面例子中:
public toString(){
String st;
st = super.toString();
}
父类对象与子类对象的关系类似于基本数据与类型数据之间的强制转换关系,存在继承关系的父类对象和子类对象也可以在一定条件下相互转换。但是应该注意以下几点:
a. 子类对象可以被视为其父类的一个对象
b. 父类对象不能被当做其某一个子类对象
c. 如果一个方法的形式参数定义的是父类对象,那么调用这个方法时,可以使用子类对象作为实际参数。
多态性与重载
多态性体现在两个方面:由于方法重载实现的静态多态性和由于方法覆盖实现的动态多态性。
静态多态性是在编译的过程中确定同名操作的具体操作的,动态多态性则是在程序运行过程中确定操作所针对的具体对象大的。
1. 方法的覆盖:子类重新定义与父类相同的方法是时,应与父类中方法的名称、方法的返回值类型以及方法的参数列表都完全相同。
2. 方法的重载:由于重载发生在同一个类里,不能再用类名来区分不同的方法,所以采用不同的式参数列表,包括形式参数的不同个数、类型顺序。方法重载时也不能根据返回值来区分同名不同方法。由于在调用一个方法时,可以根据类型转换隐藏方法的返回值类型,无法判断应该调用哪个方法,所以必须通过方法的参数列表的不同来区分。
抽象类与接口
抽象类没有具体的实例对象,它必须被继承,类中的抽象方法必须被重写。抽象类中不一定包含抽象方法,但是如果一个类包含了抽象方法,也就是abstract方法,那么该类就必须声明为抽象类。
A.抽象类中也可以由具体的数据和方法
B.可以声明一个抽象类的引用
接口:由于java支持单一继承,接口是java实现多重继承功能的一种手段。接口之定义了与外界交流时输入输出的格式。可以说接口大致规划了类的共同行为,具体的实现留给具体的类实现。
注意:a.接口的属性必须是public static final修饰,可以不写,系统自动默认。由于属性是最终属性,所以声明时必须指定初始值。
B.接口中的方法必须是抽象方法,可以不写abstract,系统默认。
实现接口是应该注意:
A.如果实现接口的类不是抽象类,则在实现接口的类的定义部分必须为所有抽象方法定义方法体,而且方法头部分必须与接口中完全一致,既有完全相同的返回值和参数列表。
B.如果实现接口的类是抽象类,则他可以不实现接口中的所有方法,但是对于这个抽象类的任何一个非抽象子类而言,他们父类所实现接口中的所有抽象方法都必须有实在的方法体。这些方法体可以来自父类,也可以来自子类自身,但是不允许存在未被实现的接口方法。这主要体现的事非抽象类中
不能存在抽象方法的原则。
C.接口访问控制符只有public一个表明可以被所有的类和接口使用,如果没有此修饰符,则只能被同一个包中的其他类和接口调用。
以下为一个实例:
package zwq03;
//点灯类
public class Light {
public void turnLight(int degree){
//调整灯光的亮度,0为关,100为最亮
System.out.println("电灯的亮度为:"+degree);
if(degree==0)
System.out.println("点灯关闭!");
else
System.out.println("将点灯拧到最大亮度!");
}
}
package zwq03;
//电视机类
public class TV {
public void setChannel(int channel){
//0表示关机,1表示开机切换到1频道
System.out.println("电视选择的频道为:"+channel);
if(channel==0)
System.out.println("关闭电视!");
else
System.out.println("将电视调到第"+channel+"频道!");
}
}
package zwq03;
//电灯命令类
public class LightCommand implements Command{
private Light light;//指向要控制的电灯对象
public void on(){//打开电灯设为最亮
light.turnLight(100);
}
public void off(){//关闭电灯
light.turnLight(0);
}
public LightCommand(Light light){//电灯命令器的构造函数,接受电灯对象
this.light = light;
}
}
package zwq03;
public class TVCommand implements Command {
private TV tv;//指向要控制的电视对象
private int channel;
public void on(){//设置电视的频道
tv.setChannel(channel);
}
public void off(){//关闭电视
tv.setChannel(0);
}
public TVCommand(TV tv,int channel){//构造函数,接受电视对象
this.tv = tv;
this.channel = channel;
}
}
package zwq03;
//遥控器类
public class RemoteController {
//遥控器有四个按钮分别对应四个Command对象
Command[] com= new Command[4];
protected void onPressButton(int button){
//按钮被按下是执行命令对象中的命令
if(button%2==0)
com[button].on();
else
com[button].off();
}
public void setCommand(int button,Command command){
com[button]=command;//设置每个按钮对应的命令对象
}
}
package zwq03;
//接口类
public interface Command {
void on();
void off();
}
package zwq03;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test {
public static void main(String args[]){
Light light = new Light();
TV tv = new TV();
int channel = 1;
//设置按钮和命令对象
LightCommand lico = new LightCommand(light);
//设置遥控对象为电灯
RemoteController reco = new RemoteController();
reco.setCommand(0, lico);
reco.setCommand(0, lico);
reco.onPressButton(0);
//创建电视对象,并选择所需的频道
TVCommand tvco = new TVCommand(tv,channel);
reco.setCommand(2, tvco);
reco.onPressButton(2);
reco.setCommand(3, tvco);
reco.onPressButton(3);
reco.setCommand(1, lico);
reco.onPressButton(1);
}
}
测试结果:
电灯的亮度为:100
将点灯拧到最大亮度!
电视选择的频道为:1
将电视调到第1频道!
电视选择的频道为:0
关闭电视!
电灯的亮度为:0
点灯关闭!