一、抽象类
什么叫抽象方法呢?
在所有的普通方法上面都会有一个“{}”,这个表示方法体,有方法体的方法一定可以被对象直接使用。
而抽象方法,是指没有方法体的方法,同时抽象方法还必须使用关键字abstract做修饰。
而拥有抽象方法的类就是抽象类,抽象类要使用abstract关键字声明。
只有覆盖了抽象类中所有的抽象方法后,其子类才可以创建对象。否则该子类还是一个抽象类
package stu.crayue.about_abstract.core;
/**
* @author Crayue
* @version 2019年10月31日 下午4:27:32
*/
public abstract class Shape {
protected String name;
public Shape(String name) {
this.name=name;
}
public abstract double perimeter();//求周长
public abstract double area();//求面积
@Override
public String toString() {
return ("图形为"+name);
}
}
上述代码中,用abstract关键字声明Shape类为抽象类
还定义了两个抽象方法求周长和面积
要注意的是:
抽象类不能直接实例化,因为抽象类存在未实现的方法;
下面来看在Shape类基础上派生出来的Square类
package stu.crayue.about_abstract.core;
/**
* @author Crayue
* @version 2019年10月31日 下午4:34:19
*/
public class Square extends Shape {
private double length;
public Square(double length) {
super("正方形");
this.length=length;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
@Override
public double perimeter() {
return 4*length;
}
@Override
public double area() {
return length*length;
}
}
再看Rectangle类:
package stu.crayue.about_abstract.core;
/**
* @author Crayue
* @version 2019年10月31日 下午4:38:51
*/
public class Rectangle extends Shape {
private double height;
private double width;
public Rectangle(double height,double width) {
super("长方形");
this.height=height;
this.width=width;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
@Override
public double perimeter() {
return 2*width+2*height;
}
@Override
public double area() {
return width*height;
}
}
再看Circle类:
package stu.crayue.about_abstract.core;
/**
* @author Crayue
* @version 2019年10月31日 下午4:41:39
*/
public class Circle extends Shape {
private double radius;
public Circle(double radius) {
super("圆形");
this.radius=radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
@Override
public double perimeter() {
return 2*Math.PI*radius;
}
@Override
public double area() {
return Math.PI*radius*radius;
}
}
最后给一个Demo类:
package stu.crayue.about_abstract.demo;
import stu.crayue.about_abstract.core.Circle;
import stu.crayue.about_abstract.core.Rectangle;
import stu.crayue.about_abstract.core.Square;
/**
* @author Crayue
* @version 2019年10月31日 下午4:44:09
*/
public class Demo {
public static void main(String[] args) {
Square square=new Square(4.0);
System.out.println(square+"周长:"+square.perimeter());
System.out.println(square+"面积:"+square.area());
Rectangle rectangle= new Rectangle(3.0, 4.0);
System.out.println(rectangle+"周长:"+rectangle.perimeter());
System.out.println(rectangle+"面积:"+rectangle.area());
Circle circle=new Circle(2.0);
System.out.println(circle+"周长:"+circle.perimeter());
System.out.println(circle+"面积:"+circle.area());
}
}
运行结果为:
图形为正方形周长:16.0
图形为正方形面积:16.0
图形为长方形周长:14.0
图形为长方形面积:12.0
图形为圆形周长:12.566370614359172
图形为圆形面积:12.566370614359172
抽象类编程核心思想:
抽象类由”确定的成分“和”不确定的成分“构成;
”确定的成分“通常由那些类中固定的,固有的和确定的成员、方法构成;
”不确定的成分“是那些类彼此相同,又不同的成分。相同点在于,这些类都存在这些成分;不同点在于,这些成分的具体实现方法不同。
二、内部类
在一个类中,可以定义其他类,这些类称为内部类;
需要注意的是:
1.在内部类的方法中,可以直接引用外部类的所有成员与方法,并且不受权限修饰符的约束;
2.外部类可以定义内部类对象的成员;
给出一个outclass类:
package com.mec.about_inner.core;
public class OuterClass {
private int privateMember;
protected int protectedMember;
public int publicMember;
public OuterClass() {
//这里定义三种不同的权限修饰符的成员
privateMember = 1;
protectedMember = 2;
publicMember = 3;
}
//这里定义三种不同的权限修饰符的方法
private void privateFun() {
System.out.println("privateMember:" + privateMember);
}
protected void protectedFun() {
privateFun();
System.out.println("protectedMember:" + protectedMember);
}
public void publicFun() {
privateFun();
System.out.println("publicMember:" + publicMember);
}
public class InnerClass {
private int innerMember;
public InnerClass() {
innerMember = 4;
}
private void InnerFun() {
privateMember++;
protectedMember++;
publicMember++;
privateFun();
protectedFun();
publicFun();
System.out.println("innerMember:" + innerMember);
}
}
//外部类可以定义其内部类对象的成员
private InnerClass innerObject;
public void fun() {
//外部类可以实例化该成员,并且可根据内部类的对象,引用内部类的成员和方法
innerObject = new InnerClass();
innerObject.InnerFun();
System.out.println(innerObject.innerMember++);
}
}
内部类对应的class文件:
额外生成了一个名为“OuterClass$InnerClass”class文件
就表明这个类是在OuterClass类中的内部类InnerClass类
三、匿名内部类
首先给出一个简单的抽象类:
package stu.crayue.about_abstract.core;
/**
* @author Crayue
* @version 2019年10月31日 下午5:28:00
*/
public abstract class Bird {
private String name;
public Bird(String name) {
this.name = name;
}
public abstract String cry();
public void print( ) {
System.out.println( name + "的叫声:" + cry());
}
}
抽象类不能直接实例化,我们试着非实例化下:
package stu.crayue.about_abstract.demo;
import stu.crayue.about_abstract.core.Bird;
/**
* @author Crayue
* @version 2019年10月31日 下午5:29:14
*/
public class Test {
public static void main(String[] args) {
Bird jiujiu = new Bird("百灵鸟") {
@Override
public String cry() {
return "啾啾啾啾";
}
};
jiujiu.print();
//第二种手段的展示
new Bird("嘤嘤怪") {
@Override
public String cry() {
return "嘤嘤嘤";
}
}.print();
}
}
实质上我们生成了一个没有机会命名的类,所以这个类为匿名类;
它不能再产生其他对象,但是它会生成相应的类文件;
匿名内部类的优点:
1.不需要明确的生成派生类,对于简单问题,明显提高编程效率
2.在需要时临时产生匿名内部类,实现抽象方法,这样更灵活
3.一个匿名内部类对应一种抽象方法的实现,这样更紧凑