目录:
一、多态
二、抽象类
三、接口
接面对对象编程01
一、多态
- 多态:思想->一个事物,表现出不同的形态
- 封装;增加了程序的安全性
- 继承:为了代码的重用
什么是多态呢?
理解多态:
* 同一个引用调用同样的方法,表现出多种不同种形态。
* 这种思想就叫多态,用到了动态绑定
class Shape{
public void draw(){
}
}
class Rect extends Shape{
public void draw(){
System.out.println("■");
}
}
class Cycle extends Shape{
public void draw(){
System.out.println("●");
}
}
class Flower extends Shape{
public void draw(){
System.out.println("❀");
}
}
public class TestDemo {
public static void drawMap(Shape shape){
shape.draw();
}
public static void main(String[] args) {
/* Rect rect = new Rect();
drawMap(rect);
Cycle cycle = new Cycle();
drawMap(cycle);
Flower flower = new Flower();
drawMap(flower);*/
// 或者直接这样
drawMap(new Rect());
drawMap(new Cycle());
drawMap(new Flower());
}
}
运行结果:
在这个代码中, 前面的代码是 类的实现者 编写的, TestDemo这个类的代码是 类的调用者 编写的
.当类的调用者在编写 drawMap 这个方法的时候, 参数类型为 Shape (父类), 此时在该方法内部并不知道, 也不关注当 前的shape 引用指向的是哪个类型(哪个子类)的实例. 此时 shape 这个引用调用 draw 方法可能会有多种不同的表现(和 shape对应的实例相关), 这种行为就称为 多态
* 多态的好处:
* 1、减低了类的使用成本
* 2、减低了圈复杂度、避免使用大量的if else
* 3、可扩展能力强
再来看一下的代码
class Shape{
public void draw(){
}
}
class Rect extends Shape{
public void draw(){
System.out.println("■");
}
}
class Cycle extends Shape{
public void draw(){
System.out.println("●");
}
}
class Flower extends Shape{
public void draw(){
System.out.println("❀");
}
}
public class TestDemo {
public static void drawShapes(){
Rect rect = new Rect();
Cycle cycle = new Cycle();
Flower flower = new Flower();
String[] shapes = {"cycle","rect","cycle","rect","flower"};
for(String shape : shapes){
if(shape.equals("cycle")){
cycle.draw();
}else if(shape.equals("rect")){
rect.draw();
}else if(shape.equals("flower")){
flower.draw();
}
}
}
public static void main(String[] args) {
drawShapes();
}
运行结果:
这是未使用多态的。
再来看使用了多态的代码
public class TestDemo {
public static void draw(Shape shape){
shape.draw();
}
public static void drawShapes(){
Shape[] shapes = {new Cycle(),
new Rect(),new Cycle(),
new Rect(),new Flower() };
//数组不是相同数据类型的集合吗,为什么可以这样放呢?
// 按道理说,这里只能放Shape类型的数据,那么这里为什么可以放其他
// 类型的数据类型呢? //因为发生了向上转型
// 请看这里,Shape shape = cycle;我们知道可以这样做,此处指的就是shape这个引用,
// 引用了cycle所引用的对象,而父类引用子类,发生了向上转型。
for(Shape shape:shapes){
draw(shape);
}
// 顺便复习数组的一种遍历方式
/* for(int x : array){
System.out.print(x+" ");
}
System.out.println();
*//**
* 原理:便利array里面的每一个元素,把每一个元素取出来
* 然后都赋值给了x,最后打印x。直到数组array里面的元素全部都遍历完成
**/
}
public static void main(String[] args) {
drawShapes();
}
除去注释,可以发现代码简洁了很多,也不用使用大量的if else语句。
二、抽象类
抽象类 抽象方法的类,叫做抽象类
- 要点:
- 1、不能被实例化
- 2、继承了就要重写抽象方法
- 3、不能是final的
顺便了解下 final 关键字
- 1.final修饰变量(常量,这个常量不能再被修改)
- 2.final修饰类,密封类:当前类不能再继承
- 3.final修饰方法,密封方法:该方法不能进行重写
既然抽象类不能实例化,那么如果我想调用抽象类里面的普通方法,
该怎么做呢?
方法的调用是通过对象的引用来调用,很显然抽象类类无法实例化。
- 1、可以在子类里通过super来进行调用。super.方法
- 2、如果这个方法是静态的方法 public static void fun(){},
- 则可以直接通过类类名来进行调用。Shape.func();
- 3、Shape shape = new Rect();
- shape.func();
- 通过向上转型,抽象类父类引用非抽象类子类,就能够调用抽象类父类的方法
请看代码:
package 抽象类;
import java.util.Random;
abstract class Shape{
/* 在普通类里是不能有抽象方法的,而在抽象类里头
既可以拥有抽象方法,也可以有非抽象方法*/
// 抽象方法:如果一个方法,没有具体的实现,那么就可以用abstract修饰
public abstract void draw();//没有具体的实现
public void func(){
System.out.println("faq!!!");
}
public static void func2(){
System.out.println("zfp!!!");
}
}
class Rect extends Shape{
@Override
public void draw() {
//1、在子类的方法里通过super进行调用
super.func();
}
}
public class Testdemo {
public static void main(String[] args) {
//1、在子类的方法里通过super进行调用
Rect rect = new Rect();
rect.draw();
// 2、静态方法直接通过类名进行调用
Shape.func2();
// 3、通过向上转型,抽象类父类引用非抽象类子类,就能够调用抽象类父类的方法
Shape shape = new Rect();
shape.func();
//再次复习一下
/* 如果发生了向上转型,那么通过父类引用,来调用方法
或者成员变量的时候,只能调用父类自己的成员变量或者方法!!*/
}
}
运行结果:
关于抽象类,还需要注意的几点是:
- 当一个非抽象类,继承了抽象类,则当前类一定要重写抽象方法
- 再次用普通类来继承,则之前的抽象类里的抽象方法,都必须重写
abstract class Shape{
public abstract void draw();//没有具体的实现
public void func(){
System.out.println("faq!!!");
}
}
//当一个非抽象类、继承了抽象类则当前类一定要重写
/*class Rect extends Shape{
@Override
public void draw() {
}
}*/
//如果不想重写的话呢?让普通类变为抽象类
abstract class Rect extends Shape{
public abstract void funcc();
}
//但是,如果再次用普通类来继承,则之前的抽象类里的抽象方法,都必须重写
//alt+回车,重写
class A extends Rect{
@Override
public void draw() {
}
@Override
public void funcc() {
}
}
抽象类的使用:
abstract class Shape{
public abstract void draw();//没有具体的实现
public void func(){
System.out.println("faq!!!");
}
}
class Rect extends Shape{
@Override
public void draw() {
System.out.println("■");
}
}
class Cycle extends Shape{
@Override
public void draw() {
System.out.println("○");
}
}
public class Testdemo {
public static void drawMap(Shape shape){
shape.draw();
}
public static void main(String[] args) {
drawMap(new Rect());
drawMap(new Cycle());
// 也是可以发生向上转型,动态绑定的,使用多态
}
}
运行结果:
总结:
- 抽象方法:如果一个方法,没有具体的实现,那么就可以用abstract修饰
- 1、抽象类不能被实例化。Shape shape = new Shape();//error
- 2、//在普通类里面是不能有抽象方法的,而在抽象类里
- 既可以有抽象方法,也可以包含非抽象方法
- 3、当一个普通的类,继承了一个抽象类,那么这个普通类一定要实现抽象类当中的方法
- 4、当一个普通类,继承了抽象类,但是又不想实现这个抽象类当中的抽象方法(重写),
- 那么这个普通类,可以改为,抽象类
- 5、当一个普通类,继承了上述第4条说的那个抽象类,那么重写的就是两个抽象类的抽象方法了。总结一句话:出来混,迟早要还的!!!
- 6、抽象类本身是不可以被实例化的,就是为了继承的。自然是不能被final修饰的
- 7、抽象方法就是为了重写的,你不可以把抽象方法用final修饰。
- 8、抽象类父类的普通方法,在类外也可以被调用,但需要让父类引用 去 引用子类对象
- 或者子类中用super访问抽象类父类的成员变量或者成员方法
- 9、抽象类最大的意义就是为了被继承
三、接口
- java是单继承
- 接口的出现就是为了多继承
接口是使用关键字intetface来修饰的,接口也是没办法实例化对象的。与抽象类不同,在接口中,只能有抽象方法。且接口中的所有方法,都是没办法具体实现的。
- 接口:
- 1、他是使用关键字intetface来修饰的,接口当中的方法,
- 默认都是抽象方法。public abstract
- 2、接口当中,可以定义成员变量。成员变量默认是public static final
- 3、接口当中的所有方法,都是没有具体实现的、
- 4、在JDk1.8开始,接口中的方法可以有具体实现,但是这个方法必须是default修饰的。
- 5、接口也是不可以被实例化的 IShape iShape = new IShape();error
- *6、接口的使用:类 implements
- *7、一个类可以实现多个接口,通过关键字implements。但是注意、
- 一定要重写接口里面的抽象类方法
package 接口;
// 接口在命名的时候一般以大写字母I开头
interface IShape{
void draw();
// 默认是public abstract void draw();建议这样简写
int a = 10;
// 默认是public static final a = 10;
/* public void func1(){
// 报错了,为什么?
}*/
/**
* 接口中的所有方法,都是没法具体实现的。
* 但是,在jdk1.8开始,接口中的所有方法可以有具体实现,但是这个
* 方法必须是default修饰的
* 比如:
*/
default void func(){
System.out.println("faq!!!");
}
}
class Cycle implements IShape{
@Override
public void draw() {
System.out.println("○");
}
}
class Rect implements IShape{
@Override
public void draw() {
System.out.println("■");
}
}
public class Test {
public static void drawMap(IShape iShape){
iShape.draw();
}
public static void main(String[] args) {
/* //接口无法实例化对象
IShape iShape = new IShape();error*/
/*// 但是可以发生向上转型
IShape iShape = new Rect();*/
//使用多态
drawMap(new Rect());
drawMap(new Cycle());
}
}
- 8、如果两个接口,方法名相同。此时在类里面,
- 只需要重写这一个方法就好,但是最终调用的,就是这一个方法
- 建议大家,既然接口都不一样,那么就不要有同样的方法
- 9、interface D extends A,B 一个接口可以扩展多个接口,
- 也就是说,D接口具备了A接口和B接口的功能
- 如果将来D接口被实现,那么这个实现D接口的类,就要重写A,B,D,3个接口的方法了
//接口D扩展了A,B的接口
interface D extends A,B{
void funcD();
}
本篇完,后续作补充