抽象类
什么是抽象类?
抽象类其实就是父类,抽象类中定义了所有子类应该共用的形式,但是并没有实现,而是靠各个子类去实现自己个性化的功能,也就是个性化定制。
那么什么是接口呢?
如果说这个抽象类。它还有一些方法是可以实现的,可以让子类去继承的,但是接口则完全没有方法的实现可以让子类去继承,都是定义的方法的标准。
那么接口有什么用呢?又不能继承又不能使用?
在现实生活中,很多电视剧电影,上映的时候都会减掉很多镜头,为什么呢?就是因为广电总局出了一些标准,比如说不能衣服领子不能低于多少,画面不能过于血腥暴力,他们自己不负责减他们是出标准的人,就要有拍电影的人去负责来实现这个标准,所以这就是现实中标准和实现的关系,其实接口就是程序中的标准。
一、抽象类、接口和内部类
抽象类和抽象方法
●抽象类就是仅定义所有子类共享的形式,而没有定义具体实现细节的父类
(父类实在不知道怎么帮子类实现,但是这些功能又是必须的,于是只好给出定义,靠子类自力更生。何时使用抽象类呢?今后只要是父类中的某些功能无法帮子类实现,就将父类定义为抽象类)
●语法: public abstract class类名… .
●抽象类中,那些只有方法定义,没有实现细节的方法就叫抽象方法;
●语法: [访问修饰符] abstract返回值类型方法名(;
●一个类中如果包含抽象方法,该类应该用abstract关键字声明为抽象类;
●如果一个类继承了抽象类,必须重写其抽象方法(除非该类也声明为抽象类)。不同的子类可以有不同的实现。
听故事学抽象
package day08;
/**
* 封装父亲属性和功能的类
* 因为内部包含抽象方法所以也要定义为抽象类
*/
public abstract class Father {
/**
* 父亲养育儿女的方法
* 儿女可以无条件继承
* @return 养育的结果
*/
public String raise(){
return "学业有成,成家立业";
}
/**
* 父亲请求子女帮忙偿还债务
* 也就是说,父亲自己无法完成
* @return 每个子女负担债务
*/
public abstract double pay();
}
封装大儿子的类
package day08;
/**
* 封装大儿子的类
*/
public class Child1 extends Father{
//编译错误:因为只要继承了抽象类,就必须重写父类的抽象方法!
// 解决: 鼠标方法在错误上,选择add unimplemented method
@Override
public double pay() {
return 10;//大儿子给10万
}
}
封装二儿子的类
package day08;
/**
* 封装二儿子的类
*/
public class Child2 extends Father{
@Override
public double pay() {
return 25;//二儿子给25万
}
}
封装小儿子的类
package day08;
/**
* 封装小儿子的类
*/
public class Child3 extends Father{
@Override
public double pay() {
return 7.5;//小儿子给7.5万
}
}
封装小女儿的类
package day08;
/**
* 封装小女儿的类
*/
public class Child4 extends Father{
@Override
public double pay() {
return 5;//小女儿给5万
}
}
测试类:
切记!抽象类不能实例化
package day08;
public class Test {
public static void main(String[] args) {
//Father f=new Father(); 编译错误:切记!抽象类不能实例化
//因为抽象类都是不完整的!
//要想使用抽象类中的普通方法,只能通过子类对象继承后调用
//父亲抚养4个孩子成人
Child1 c1=new Child1();
Child2 c2=new Child2();
Child3 c3=new Child3();
Child4 c4=new Child4();
System.out.println("大儿子"+c1.raise());
System.out.println("二儿子"+c2.raise());
System.out.println("小儿子"+c3.raise());
System.out.println("小女儿"+c4.raise());
//结论:子类可以继承抽象类中的已实现方法和继承普通父类完全一样。
}
}
结论:子类可以继承抽象类中的已实现方法和继承普通父类完全一样。
案例:父亲将4个儿女叫到一起
package day08;
public class Test {
public static void main(String[] args) {
Child1 c1=new Child1();
Child2 c2=new Child2();
Child3 c3=new Child3();
Child4 c4=new Child4();
System.out.println("大儿子"+c1.raise());
System.out.println("二儿子"+c2.raise());
System.out.println("小儿子"+c3.raise());
System.out.println("小女儿"+c4.raise());
//结论:子类可以继承抽象类中的已实现方法和继承普通父类完全一样。
//父亲将4个儿女叫到一起
//程序中,集中保存东西,都是使用数组
//问题1:4个儿女对象,数据类型不相同,怎么放到同一个数组中呢?
//解决:父类型的引用,可以指向任何子类的对象
//完全可以将数组元素的类型,统一定义为父类型
Father[] children={c1,c2,c3,c4};
System.out.println("大儿子 | 二儿子 | 三儿子 | 小女儿");
//因为每个孩子都帮父亲实现了pay方法。可以循环调用每一个孩子的pay方法
for (int i = 0; i < children.length; i++) {
//问题2:children中每个元素是什么类型?凭什么可以调用子类实现的pay方法?
//原因:children中的每一个元素都是Father父类
//子类都重写了父类抽象方法pay,所以父类型的引用,
//可以调用子类对象重写的父类方法
System.out.print(children[i].pay()+"万 ");
}
System.out.println();
System.out.println("---------分割线--------");
//父亲公布的遗产:
for (int i = 0; i < children.length; i++) {
System.out.print(children[i].pay()*5+"万 ");
}
}
}
抽象类不可以实例化,因为父类是不完整的:
Father father=new Father(); //编译错误
另外,即使一个类中没有抽象方法 ,也可以使用abstract修饰类。作用就是不让该类实例化。
abstract VS final:
抽象类:天生就用来被继承!不继承,就没有任何意义。
Final :专门用来禁止被继承!和抽象类的意义刚好相反!
所以: abstract和fina|不能同时修饰一个类
抽象类的意义在于:
-为其子类提供一个公共的类型一一继承的意义
-封装子类中的重复成员(避免重复)一一继承的意义
-定义抽象方法,规定子类有义务必须帮父类完成的功能一一抽象的意义