2021-11-04

抽象类和接口

1.抽象类
  类–用来描述具有共同性质的一组事物的自定义复合数据类型,class关键字创建
  public class Hello{} — 类
  抽象类–通过abstract 修饰的java类就是。
  public abstract class Hello{}—抽象类
  在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
  由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
  父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
在 Java 中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
2.为什么要有抽象类?
  例如:坐车收费,出租车有收费功能【1元/公里】,公交车有收费功能【全程1元】。
  出租车/公交车----汽车—收费功能
  出租车 extends 汽车 —重写收费功能—【1元/公里】
  公交车 extends 汽车 —重写收费功能— 【全程1元】
  我们可以理解为汽车就是一个抽象类,出租车/公交车都是汽车的子类,出租车/公交车就会从汽车中继承来收费功能然后在根据自身的实际情况,重写收费功能就可以得到属于自己的收费功能实现。
  抽象类的子类往往都是同一种类型。
  抽象类实际上就是提供同一种类型事物的公共内容,由抽象类的子类根据自身的实际情况,来实现这个抽象类提供的公共内容。这样子类就不需要创建这个公共内容,只需要继承来重写一下就好。
3.抽象类中可以有哪些元素?
  类–实例变量,静态成员变量,构造方法,实例方法,静态方法
  抽象类–实例变量,静态成员变量,构造方法,实例方法,静态方法,【抽象方法】
  误区:判断一个类是不是抽象类不看有没有抽象方法。
  方法基本格式:修饰符 返回值 名称([参数]){方法体}
  实例方法:修饰符 返回值 名称([参数]){方法体}
  静态方法:修饰符 static 返回值 名称([参数]){方法体}
  构造方法:修饰符 类名([参数]){方法体}
  抽象方法:修饰符 abstract 返回值 名称([参数])
  抽象方法–使用abstract修饰的没有方法体的方法
  抽象类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。
  Abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。
  抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。
例如:

package com.wangxing.zyb1;
public abstract class TestClass{
	public int id=1001;//实例变量
	public static String name="zhangsan";//静态成员变量
	public TestClass() {
		System.out.println("构造方法");
	}
	public void shili() {
		System.out.println("实例方法");
	}
	public static void staticmethod() {
		System.out.println("静态方法");
	}
	//抽象方法--使用abstract修饰的没有方法体的方法
	//抽象方法:修饰符 abstract 返回值  名称([参数])
	public abstract void abstractmethod();
} 
package com.wangxing.zyb1;
public class TestSunClass extends TestClass{
	@Override
	public void abstractmethod() {	
	}
}
package com.wangxing.zyb1;
public class Main1 {
	public static void main(String[] args) {
		TestSunClass tsc1=new TestSunClass();
		System.out.println(tsc1.id);
		System.out.println(TestSunClass.name);
		tsc1.shili();
		TestClass.staticmethod();
	}
}

在这里插入图片描述
4.抽象类的具体用法
  1.抽象类不能new,借助子类访问抽象类中的实例元素。
  2.普通的java类继承了抽象类,就需要重写抽象类中的所有抽象方法,否则将这个普通的java类改成抽象类。
  3.抽象类可以继承其他的抽象类,可以不用重写抽象方法。
  4.利用上转型对象创建出抽象类对象
  5.抽象类对象可以访问抽象类中的实例变量、类变量、构造方法、实例方法、类方法、【抽象方法实际上是子类重写以后的方法】。
  6.当某一个普通的java类中的方法参数是抽象类类型的时候,可以传递上转型对象,也可以是抽象类的子类对象。
例如:

package com.wangxing.zyb3;
public abstract class TestClass {
	//抽象方法
	public abstract void info();
}
package com.wangxing.zyb3;
public class TestSunClass extends  TestClass{
	public void info() {
		System.out.println("TestSunClass子类重写父类TestClass的抽象方法");
	}
}
package com.wangxing.zyb3;
public class Person {
	public void testPerson(TestClass tc) {
		System.out.println("Person类的实例方法");
		tc.info();
	}
}
package com.wangxing.zyb3;
public class Main {
	public static void main(String[] args) {
		//抽象类不能new
		//new TestClass();
		//如果我们需要创建出抽象类的对象,就需要借助上转型对象
		//上转型对象--子类的对象赋值给父类的变量
		TestClass  tc1=new TestSunClass();
		tc1.info();
	}
}
package com.wangxing.zyb3;
public class Main {
	public static void main(String[] args) {
		Person per1=new Person();
		TestClass tc1=new TestSunClass();//上转型对象
		per1.testPerson(tc1);
		TestSunClass tsc=new TestSunClass();//子类对象
		per1.testPerson(tsc);
	}
}

在这里插入图片描述
在这里插入图片描述
5.上转型对象
 上转型对象–子类的对象赋值给父类的变量,此时子类对象就向上转型成父类对象
 上转型对象不能方法子类本身的变量和方法,如果我们需要访问子类本身的变量和方法,需要通过强制类型转换
例如:

package com.wangxing.zyb2;
public class Person {
	public void testPerson() {
		System.out.println("Person类的实例方法");
	}
}
package com.wangxing.zyb2;
public class Student extends Person{
	public void testStudent() {
		System.out.println("Student类的实例方法");
	}
}
package com.wangxing.zyb2;
public class Main {
	public static void main(String[] args) {
		//上转型对象--子类的对象赋值给父类的变量,此时子类对象就向上转型成父类对象
		Person per=new Student();
		per.testPerson();
		//上转型对象不能方法子类本身的变量和方法
		//per.testStudent(); 
		//如果我们需要访问子类本身的变量和方法,需要通过强制类型转换
		Student stu=(Student)per;
		stu.testPerson();
		stu.testStudent();
	}
}

利用上转型对象创建出抽象类对象
6.卖水果实例

package com.wangxing.zyb4;
public abstract class ShuiGuo {
	public abstract void eat();
}
package com.wangxing.zyb4;
public class PingGuo extends ShuiGuo{
	@Override
	public void eat() {
			System.out.println("我是苹果");
	}
}
package com.wangxing.zyb4;
public class XiGua extends ShuiGuo{
	@Override
	public void eat() {
		System.out.println("我是西瓜");
	}
}
package com.wangxing.zyb4;
public class ShangRen {
	public static ShuiGuo sellShuiGuo(String name) {
		ShuiGuo sg=null;
		if(name.equals("苹果")) {
			sg=new PingGuo();
		}
		if(name.equals("西瓜")) {
			sg=new XiGua();
		}
		return sg;
	}
}
package com.wangxing.zyb4;
import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		System.out.println("你好需要什么");
		Scanner input=new Scanner(System.in);
		String name=input.next();
		ShuiGuo sg=ShangRen.sellShuiGuo(name);
		sg.eat();
	}
}

在这里插入图片描述
1.接口
 通过interface关键字修饰的java元素就是接口。
 格式:public interface 接口名{}
   interface 接口名{}
2.为什么要有接口?
 为了克服java的单继承,接口可以被实现多个
 例如:收费,出租车有收费功能【1元/公里】,飞机有收费功能【全程1000元】
 出租车与飞机不是同一类事物,但是有相同的功能
 接口实际上就是提供不同类型事物的公共内容,由接口的子类根据自身的实际情况,来实现这个接口提供的公共内容。这样子类就不需要创建这个公共内容,只需要继承来重写一下就好。

3.接口中的元素
接口中可以有常量、静态方法、抽象方法。
1、接口中变量一定是 public static final修饰的常量。
2、接口中的静态方法一定是public修饰的,public可以被省略。
3、接口中的抽象方法一定是public abstract修饰的,public abstract可以省略
例如:

package com.wangxing.zyb5;
public interface  TestInterface {
	//静态成员变量
	//接口中变量一定是 public static  final修饰的常量。
	int id=1001;
	static String name="zhangsan";
	public int age=23;
	//静态方法
	//接口中的静态方法一定是public修饰的,public可以被省略。
	static void staticMethod(){}
	//抽象方法
	//接口中的抽象方法一定是public  abstract修饰的,public  abstract可以省略
	void abstractMehod();
}
package com.wangxing.zyb5;
public class Main {
	public static void main(String[] args) {
		System.out.println(TestInterface.id);
		System.out.println(TestInterface.name);
		System.out.println(TestInterface.age);
		TestInterface.staticMethod();
	}
}

在这里插入图片描述
4.接口的用法
  1.接口不能new,如果需要访问抽象方法需要借助接口子类
  2.类可以通过implements关键字去实现一个/多个接口
  3.普通的类去实现一个/多个接口,就需要将每一个接口中的抽象方法重写,否则就需要将这个普通的类改成抽象类.
  4.抽象类去实现一个/多个接口,不需要重写接口中的抽象方法。
  5.接口可以继承接口,并且可以继承父接口中的所有元素.
  6.利用接口回调对象创建出接口对象
  7.当某一个普通的java类中的方法参数是接口类型的时候,可以传递接口回调对象,也可以是接口的子类对象。

package com.wangxing.zyb5;
public class Person implements TestInterface,DoxInterface{
	//重写DoxInterface中的抽象方法
	@Override
	public void docinfo() {
	}
	//重写TestInterface中的抽象方法
	@Override
	public void abstractMehtod() {
	}
}
public interface DoxInterface extends TestInterface{
	//抽象方法
	void docinfo();
}
package com.wangxing.zyb6;
public class Person {
	public static void Test(TestInterface hello) {
		hello.info();
	}	
}
package com.wangxing.zyb6;
public class Main {
	public static void main(String[] args) {
		//接口不能new
		//new TestInterface();
		//接口回调对象--接口的子类对象赋值给接口变量
		TestInterface  ti1=new TestSunClass();
		//接口回调对象只能访问接口的抽象方法,实际上访问子类重写以后的抽象方法
		ti1.info();
		//接口回调对象不能访问子类本身的方法,如果要访问就需要强制类型转换
		ti1.test1();
		TestSunClass tc=(TestSunClass)ti1;
		tc.test1();
	}
}

在这里插入图片描述
5.接口回调对象
 接口回调对象与上转型对象很相似
 接口回调对象–接口的子类对象赋值给接口变量
  1.接口回调对象只能访问接口的抽象方法,实际上访问子类重写以后的抽象方法
  2.接口回调对象不能访问子类本身的方法,如果要访问就需要强制类型转换
例如:

package com.wangxing.zyb6;
public class TestSunClass2 implements TestInterface{
	@Override
	public void info() {
		System.out.println("ceshi");
	}
}
package com.wangxing.zyb6;
public class Main {
	public static void main(String[] args) {
		Person Person1=new Person();
		Person1.Test(new TestSunClass());
		Person1.Test(new TestSunClass2());	
	}
}

在这里插入图片描述
抽象类与接口的区别?

抽象类 接口
abstract class interface
extends 一个 implments 一个/多个
提供同类型事物的公共内容 提供不同类型事物的公共内容
抽象类中的元素实例变量、类变量、构造方法、实例方法、类方法、【抽象方法】 接口中可以有类变量、JDK8.0类方法、抽象方法。且都是public修饰符修饰的
抽象方法可以有页可以没有 接口中大部分都是抽象方法

关键字
1.static 静态修饰符
  1.被static修饰的变量是静态成员变量,可以类名访问,也可以对象访问
  2.被static修饰的访问是静态方法,可以类名访问,也可以对象访问
  3.同一个类中静态方法不能访问实例元素,this不能出现。
2.this 当前类对象
  1.出现在哪个类中就表示哪个类的对象
  2.在当前类中的构造方法/实例方法中访问当前类中的变量和方法,可以省略。
  3.在当前类中的构造方法/实例方法中访问被隐藏的成员变量时不能省略。
3.super 父类的对象
  1.出现在子类中的构造方法第一句时,super()父类无参数构造方法/super(参数)父类有参数构造方法。
  2.出现在子类中的实例方法是,表示访问父类的变量/方法,访问被隐藏的父类变量,super.变量名称,此时这个super表示父类的对象,一般指访问没有重写之前的父类方法,super.方法名称([参数]),此时这个super表示父类的对象
4.final 终极修饰符
1.被fianl修饰的类,不能被继承,没有子类

public final class TestClass {
}
//错误:The type TestSunClass cannot subclass the final class TestClass
public class TestSunClass extends TestClass{
}

2.被fianl修饰的变量,就是常量,不能被重新赋值

package com.wangxing.test7;
public class Main {
	public  static  void  main(String args[]){
		final String name="zhangsan"; //局部变量
		System.out.println("name=="+name);
		//错误:被fianl修饰的变量,就是常量,不能被重新赋值
		//name="lisi";
		System.out.println("name=="+name);
	}
}

3.被fianl修饰的方法,不能被重写。

public  class TestClass {
	public final void  info(){
		System.out.println("TestClass类的实例方法");
	}
}
public class TestSunClass extends TestClass{
	/*
	被fianl修饰的方法,不能被重写。
	public  void  info(){
		System.out.println("重写从父类继承的info方法");
	}
	*/	
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_53123681/article/details/121149318