多态、抽象類、接口
-
-
- 多态
- 抽象類
- 接口
-
多态
多态存在的條件:
1.建立在繼承關系上
2.發生向上轉型(父類引用指向子類的執行個體)
3.子類必須重寫和父類同名的方法
具體來看多态示例吧
class Shape{
public void draw(){
}
}
class Cycle extends Shape{
@Override //注解 表示有方法重寫同時友善檢查重寫方法
//重寫了父類Shape的draw方法,對于下面的Rect和Floewr也一樣
public void draw() {
System.out.println("○");
}
}
class Rect extends Shape{
@Override
public void draw() {
System.out.println('□');
}
}
class Flower extends Shape{
@Override
public void draw() {
System.out.println("❀");
}
}
//以上為類的實作者編寫
//======================來一條分割線助威==============================//
//以下為類的調用者編寫
public class TrqDemo {
public static void main(String[] args) {
Shape shape1 = new Cycle(); //父類引用shape1指向子類Cycle對象
Shape shape2 = new Rect();
Shape shape3 = new Flower();
//向上轉型發生時機有三種:①直接指派調用 ②方法傳參 ③方法傳回值
//在這裡我們使用: 方法傳參
drawShape(shape1);
drawShape(shape2);
drawShape(shape3);
}
public static void drawShape(Shape shape){
shape.draw();
}
}
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNCM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPR9kMJRkTzcGROBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL5AjN4AzM0IjM4ETMwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
通過上面的例子相信大家對多态一目了然,那麼多态的好處是什麼呢?
1.讓類的調用者不需要這個類的類型是什麼,隻需要知道對象是否具有某個方法即可
==2.降低代碼的“圈複雜度”,避免使用了大量的if-else
抽象類
在上面的列印圖形示例中,我們發現Shape父類中draw方法沒有實際的實作,主要的繪制都是子類中的draw方法實作的,對于這種沒有具體實作的方法,我們可以将它設計為抽象方法(abstract method),包含抽象方法的類,我們稱之為抽象類(abstract class)
具體來看抽象類示例吧
抽象類:最大的意義為了被繼承
1.抽象類不能被直接執行個體化
2.抽象方法不能被private修飾,因為抽象方法就是用來被重寫的
3.抽象類中可以包含其他的非抽象方法,可以包含字段,非抽象方法和普通方法一樣可被重寫,可被子類調用
4.抽象類可被普通類與抽象類繼承。被普通類繼承時,普通類中一定要重寫抽象類中的抽象方法;被抽象類繼承時,可什麼都不寫;對于兩個普通類之間的繼承,子類裡面可以什麼都不寫
5.對于抽象類,要想達到執行個體化效果,隻能建立抽象類的子類,讓子類重寫抽象類中的抽象方法
6.抽象類也可以發生向上轉型
abstract class Shape{
abstract public void draw();
// abstract protected void draw(); 可以
// abstract void draw(); 可以
// abstract private void draw(); 堅決不可以被private修飾
void fine(){
System.out.println("fine!!!");
}
}
class Rect extends Shape{
@Override
//這裡draw方法必須被public修飾 對于重寫而言 子類方法通路權限必須大于父類
public void draw(){
System.out.println("□□□");
}
}
//普通類繼承抽象類,普通類不想實作抽象類中的抽象方法時,可被修飾為抽象類
abstract class Cycle extends Shape{
}
public class TrqDemo1 {
public static void main(String[] args) {
// Shape shape = new Shape(); 編譯錯誤,抽象類不能被執行個體化
Shape shape = new Rect();
shape.draw(); //直接指派
drawMap(new Rect()); //方法傳參
drawMap().draw(); //方法的傳回值
}
public static void drawMap(Shape shape){
shape.draw();
}
public static Shape drawMap(){
Rect rect = new Rect();
return rect;
}
}
接口
接口是抽象類的更進一步,抽象類中除了抽象方法還可以包含非抽象方法和字段,而對于接口,接口中方法隻能為抽象方法,字段隻能為靜态常量。可以算抽象類的特殊形式,用interface修飾。
接口: 關鍵字interface 接口最大的意義讓Java實作了多繼承的效果
1.抽象類還可以包含非抽象方法和字段,而接口的方法都是抽象方法用public abstract修飾,字段隻能包含靜态常量用public static final修飾
2.JDK1.8引入新的特性,default修飾的方法可以有具體的實作
3.接口無法執行個體化
4.接口與類之間的關系是implements
5.一個類可以實作多個接口;一個類繼承一個父類同時也可以實作多個接口
6.一個接口可以擴充多個接口通過extends實作
7.接口的出現就是為了解決Java多繼承問題
接口執行個體1:一個類實作一個接口
interface IShape{
public abstract void draw(); //public和abstract可丢棄
public static final int val=66;
}
//展示了普通類和接口之間的關系
class Cycle implements IShape{
@Override
public void draw(){
System.out.println("⚪");
}
}
public class TrqDemo2{
public static void main(String[] args) {
IShape shape = new Cycle();
shape.draw(); //直接指派調用
drawMap(shape); //方法傳參
drawMap().draw(); //方法傳回值調用
}
public static void drawMap(IShape shape){
shape.draw();
}
public static IShape drawMap(){
return new Cycle();
}
}
接口執行個體2:一個類實作多個接口
//表示一組動物
class Animal{
protected String name;
public Animal(String name){
this.name = name;
}
}
//一組接口
interface IFlying{
void fly();
}
interface IRunning{
void run();
}
interface ISwimming{
void swim();
}
//建立具體的動物類
class Cat extends Animal implements IRunning{
public Cat(String name){
super(name);
}
@Override
public void run(){
System.out.println(this.name + "正在跑!");
}
}
class Fish extends Animal implements ISwimming{
public Fish(String name){
super(name);
}
@Override
public void swim(){
System.out.println(this.name + "正在遊!");
}
}
class Frog extends Animal implements IRunning,ISwimming{
public Frog(String name){
super(name);
}
@Override
public void run(){
System.out.println(this.name + "正在往前跳!");
}
@Override
public void swim(){
System.out.println(this.name + "正在遊泳!");
}
}
class Duck extends Animal implements ISwimming,IFlying,IRunning{
public Duck(String name){
super(name);
}
@Override
public void fly() {
System.out.println(this.name + "正在用翅膀飛!");
}
@Override
public void run() {
System.out.println(this.name + "正在用兩條腿跑!");
}
@Override
public void swim() {
System.out.println(this.name + "正在水上漂!");
}
}
//Robot沒有繼承類 擴充了一個接口
class Robot implements IRunning{
public String name;
public Robot(String name){
this.name = name;
}
@Override
public void run() {
System.out.println(this.name + "機器人正在跑!");
}
}
public class TrqDemo3 {
public static void main(String[] args) {
IRunning run = new Robot("機器一号");
run.run();
gofly(new Duck("唐小鴨"));
goRun(new Cat("唐小貓"));
goSwim(new Frog("唐小蛙"));
}
public static void gofly(IFlying fly){
fly.fly();
}
public static void goRun(IRunning run){
run.run();
}
public static void goSwim(ISwimming swim){
swim.swim();
}
}
接口執行個體3:接口擴充多個接口
一個類繼承一個父類同時實作多個接口
interface A {
void funcA();
}
interface B {
void funcB();
}
interface C {
void funcC();
}
//接口也可以擴充多個接口
interface D extends A,B,C{
void funcD();
}
//接口D擴充了三個接口,是以在類T中必須實作重寫四個抽象方法
class T implements D{
@Override
public void funcA() {
}
@Override
public void funcD() {
}
@Override
public void funcB() {
}
@Override
public void funcC() {
}
}
abstract class TestAbstract {
public abstract void funcAbstract();
}
//一個普通類繼承一個父類同時實作多個接口
class Test extends TestAbstract implements A,B,C{
@Override
public void funcA() {
}
@Override
public void funcB() {
}
@Override
public void funcC() {
}
@Override
//普通類繼承抽象類時,必須重寫父類抽象方法
public void funcAbstract() {
}
}
public class TrqDemo4 {
public static void main(String[] args) {
}
}
明天光芒依舊,加油。1.18