抽象类概述
当编写一个类时,我们往往会为该类定义一些方法,这些方法是用来描述该类的功能具体实现方式,那么这些方法都有具体的方法体。
但是有的时候,某个父类只是知道子类应该包含怎么样的方法,但是无法准确知道子类如何实现这些方法。比如一个图形类应该有一个求周长的方法,但是不同的图形求周长的算法不一样。那该怎么办呢?
分析事物时,发现了共性内容,就出现向上抽取。会有这样一种特殊情况,就是方法功能声明相同,但方法功能主体不同。那么这时也可以抽取,但只抽取方法声明,不抽取方法主体。那么此方法就是一个抽象方法。
1、 案例代码:
package com.itheima_01;
/*
* abstract:关键字,用于修饰方法和类
* 抽象方法:不同类的方法是相似,但是具体内容又不太一样,所以我们只能抽取他的声明,没有具体的方法体,没有具体方法体的方法就是抽象方法
* 抽象类:有抽象方法的类必须是抽象类
*
* 注意:一个类继承了抽象类需要重写他所有的抽象方法,否则这个类就得是抽象类
*/
public class AbstractDemo {
}
abstract class Animal1 {
public abstract void eat();
//非抽象方法子类可以不重写
public void run() {
}
}
class Cat1 extends Animal1 {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
/*public void eat() {
System.out.println("猫吃鱼");
}*/
}
abstract class Dog1 extends Animal1 {
/*public void eat() {
System.out.println("狗吃屎");
}*/
}
2、 抽象类的特点
抽象类的特点:
抽象方法只能在抽象类里面
抽象类和抽象方法必须被abstract修饰
抽象类不能创建对象(不能实例化)
抽象类中可以有非抽象的方法
抽象类和类的关系也是继承
一个类继承了抽象类要么重写所有的抽象方法,要么他自己是抽象类
案例代码:
package com.itheima_01;
/*
* 抽象类的特点:
* 抽象方法只能在抽象类里面
* 抽象类和抽象方法必须被abstract修饰
* 抽象类不能创建对象(不能实例化)
* 抽象类中可以有非抽象的方法
* 抽象类和类的关系也是继承
* 一个类继承了抽象类要么重写所有的抽象方法,要么他自己是抽象类
*/
public class AbstractDemo2 {
public static void main(String[] args) {
//Animal a = new Animal();
}
}
abstract class Animal2 {
public abstract void eat();
public void run() {
}
}
class Cat2 extends Animal2 {
@Override
public void eat() {
// TODO Auto-generated method stub
}
}
3、抽象类的成员的特点
A:抽象类的成员特点:
成员变量
可以有成员变量
可以有常量
成员方法
可以有抽象方法
可以有非抽象方法
构造方法
可以有构造方法的,需要对抽象类的成员变量进行初始化
案例代码:
package com.itheima_01;
/*
* 抽象类的成员特点:
* 成员变量
* 可以有成员变量
* 可以有常量
* 成员方法
* 可以有抽象方法
* 可以有非抽象方法
* 构造方法
* 可以有构造方法的,需要对抽象类的成员变量进行初始化
*
* final:修饰类、成员变量、成员方法
*/
public class AbstractDemo3 {
public static void main(String[] args) {
Dog d = new Dog();
d.barking();
}
}
abstract class Animal {
String name = "哮天犬";
final int num = 10;
public Animal() {
System.out.println("我是抽象类的构造方法");
}
public abstract void eat();
public void run() {}
}
class Dog extends Animal {
public void barking() {
System.out.println(name);
System.out.println(num);
}
@Override
public void eat() {
// TODO Auto-generated method stub
}
}
4、抽象类的细节
A:抽象类关键字abstract可以和哪些关键字共存?
1.private:
私有的方法子类是无法继承到的,也不存在覆盖,而abstract和private一起使用修饰方法,abstract既要子类去实现这个方法,而private修饰子类根本无法得到父类这个方法。互相矛盾。
2.final:
抽象类不能和final共存,因为抽象类自身无法创建对象,我们需要通过子类创建对象,一旦抽象类使用final关键字,那么抽象类就没有子类
抽象方法不能和final共存,因为抽象方法后期需要被子类重写,一旦加final无法重写
3.static:
抽象方法不能和static关键字共存,因为一旦加static我们就可以通过类名直接访问抽象方法,由于抽象方法没有方法体,没有任何意义,也不允许这样做
B:抽象类中是否可以不定义抽象方法?
是可以的,那这个抽象类的存在到底有什么意义呢?不让该类创建对象,方法可以直接让子类去使用
C:抽象类是否有构造函数?
有,抽象类的构造函数,是由子类的super语句来调用,用于给抽象类中的成员初始化
用关键字abstract修饰的方法称为抽象方法。
对于抽象方法,只允许声明,不允许实现(没有方法体),而且不允许finnal和abstract修饰同一方法或类,也不允许static修饰abstr方法,即abstract方法必须是实列方法。
abstra类不能用new 运算符创建对象
abstract类的子类必需重写abstra类中的方法
abstra类的对象作为上转型对象
abstract class GirlFriend {
abstract void speak();
abstract void cooking();
}
class ChinaGirlFriend extends GirlFriend {
void speak() {
System.out.println("你好");
}
void cooking() {
System.out.println("水煮鱼");
}
}
class AmericanGirlFriend extends GirlFriend {
void speak() {
System.out.println("Hello!");
}
void cooking() {
System.out.println("Roast beef");
}
}
class Boy {
GirlFriend friend;
void SetGirFriend(GirlFriend f) {
friend = f;
}
void showGirlFriend() {
friend.speak();
friend.cooking();
}
}
public class Test {
public static void main(String[] args) {
GirlFriend girl = new ChinaGirlFriend(); //girl is Upper Transition Object
Boy boy = new Boy();
boy.SetGirFriend(girl);
boy.showGirlFriend();
girl = new AmericanGirlFriend();
boy.SetGirFriend(girl);
boy.showGirlFriend();
}
}
面向抽象编程
在程序设计中我们经常会使用abstra类,因为它只关心操作,而不在意具体实现细节。
所谓的面向抽象编程,是指设计某种重要的类时,不让该类面向具体的类,而是面向抽象类。
import java.awt.*;
public class Test {
public static void main(String[] args) {
double a,b;
Pillar pillar;
Geometry bottom=null;
pillar=new Pillar(bottom,100);
System.out.println("体积"+pillar.getVolume());
bottom=new Rectangle(12,22);
pillar=new Pillar(bottom,58);
System.out.println("体积"+pillar.getVolume());
bottom=new Circle(10);
pillar=new Pillar(bottom,58);
System.out.println("体积"+pillar.getVolume());
}
}
abstract class Geometry {
abstract double getArea();
}
class Pillar {
Geometry bottom; //bottom is a variable by the abstract class geometry
double height;
Pillar(Geometry bottom, double height) {
this.bottom = bottom;
this.height = height;
}
public double getVolume() {
if (bottom == null) {
System.out.println("没有底,无法计算面积!");
return -1;
}
return bottom.getArea() * height; //Bottom can call the getArea method that the subclass overrides
}
}
class Circle extends Geometry {
double r;
Circle(double r) {
this.r = r;
}
public double getArea() {
return (3.14 * 3.14 * r);
}
}
class Rectangle extends Geometry{
double a, b;
Rectangle(double a, double b) {
this.a = a;
this.b = b;
}
double getArea() {
return a * b;
}
}
为什么使用抽象类
首先做一个分析如下:
1:定义Dog类
有颜色属性和叫的方法
2:定义Bird类
有颜色属性和叫的方法
3:定义其父类Animal
1:抽取共性颜色属性和叫的方法
1:颜色的属性可以使用默认初始化值。
2:叫的方法在父类中如何定义?
1:狗是旺旺
2:鸟是叽叽喳喳
3:可以将父类的方法定义为狗叫让鸟继承父类重写叫的方法
1:鸟怎么确定是否要重写父类方法。
2:不重写,编译和运行都没有问题,只是执行鸟叫的方法就会出现狗叫
4:父类的方法很难确定。
上方描述代码如下:
function(){
class Animal {
String color;
void shout(){
//如何定义呢?是旺旺还是叽叽喳喳?
}
}
class Dog extends Animal {
void shout() {
System.out.println("旺旺");
}
}
class Bird extends Animal {
void shout() {
System.out.println("叽叽喳喳");
}
}
那么此时使用abstract能够解决这个问题 。
4:抽象类
1:当描述一个类的时候,如果不能确定功能函数如何定义,那么该类就可以定义为抽象类,功能函数应该描述为抽象函数。
5:抽象类的实现方式
1:定义animal类
1:定义叫的方法,无法确定方法体,不写方法体
1:public void shout (); 编译失败
2:根据提示在shout的方法加入abstract修饰
1:编译失败,有新的提示
3:根据提示将类加入abstract修饰
1:编译通过
abstract class Animal {
String color;
abstract void shout();
}
class Dog extends Animal {
void shout() {
System.out.println("旺旺");
}
}
class Bird extends Animal {
void shout() {
System.out.println("叽叽喳喳");
}
}
6:抽象类的特点
1:有抽象函数的类,该类一定是抽象类。
2:抽象类中不一定要有抽象函数。
3:抽象类不能使用new创建对象
1:创建对象,使用对象的功能,抽象类的方法,没有方法体。
4:抽象类主要为了提高代码的复用性,让子类继承来使用。
5:编译器强制子类实现抽象类父类的未实现的方法。
1:可以不实现,前提是子类的也要声明为抽象的。
7:抽象的优点
1:提高代码复用性
2:强制子类实现父类中没有实现的功能
3:提高代码的扩展性,便于后期的代码维护
8:抽象类不能创建对象,那么抽象类中是否有构造函数?
抽象类中一定有构造函数。主要为了初始化抽象类中的属性。通常由子类实现。
9:final和abstract是否可以同时修饰一个类?
一定不能同时修饰。
abstract class Animal {
String name;
// 抽象类可以有构造函数
Animal() {
}
Animal(String name) {
this.name = name;
}
abstract void shout();
}
class Dog extends Animal {
Dog() {
}
Dog(String name) {
super(name);
}
void shout() {
System.out.println("旺旺");
}
}
class Demo3 {
public static void main(String[] args) {
// 抽象类不能创建对象
// Animal a=new Animal();
Dog d = new Dog("旺财");
System.out.println();
}
}