zoukankan      html  css  js  c++  java
  • 详解 抽象类

    本人在这篇博文中要讲解的知识点,和本人之前的一篇博文有所关联。因为,“抽象类” 是按照 “自下而上” 的顺序来编写所需的类,而在本人之前的博文《详解 继承(上)—— 工具的抽象与分层》中讲到的 继承 则与之相反,按照 “自上而下” 的顺序来编写所需类,那么,话不多说,现在本人就开始讲解这篇博文的主题

    抽象类的基本概念:

    首先,本人来介绍下什么是抽象类

    定义
    在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类

    那么,抽象类具有如下特点

    特点

    • 抽象类 和 抽象方法 必须用abstract关键字修饰
      抽象类格式: abstract class 类名 {}
      抽象方法格式: public abstract void eat();
    • 抽象类 不一定有抽象方法,有抽象方法的类 一定是抽象类
    • 抽象类中可以有构造方法,抽象类不能进行实例化
      问:那么要构造方法有什么作用呢?
      答曰:用于子类访问父类数据时的初始化
    • 抽象类不能直接实例化
      问:那么,抽象类如何实例化呢?
      答曰:按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
    • 抽象类的子类
      要么是抽象类
      要么重写抽象类中的所有抽象方法

    本人来通过两个例子,来展示这个知识点的应用:

    一、图形类:

    假设现在要求编写几个类可以分别根据图形的属性求出图形的 周长 及 面积。

    那么,若我们将几个图形的共性拿出来,做一个基类,之后我们再根据基类派生出各图形的方法。

    首先,我们来编写 基本图形类(BaseShape类):
    BaseShape.java:

    package com.mec.about_abstruct;
    
    public abstract class BaseShape {	//只要含抽象方法,就是抽象类,就要加上“abstract”修饰符
    	protected String name;
    	protected String type;
    	
    	protected BaseShape() {
    	}
    	
    	protected BaseShape(String name) {
    		this.name = name;
    	}
    	
    	//这两行代码,就是“抽象方法”,不在本类中实现,是专门用来给子类实现的
    	public abstract double area();	
    	public abstract double rounder();
    	
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public String getType() {
    		return type;
    	}
    
    	public void setType(String type) {
    		this.type = type;
    	}
    
    	@Override
    	public String toString() {
    		return name + "的" + type;
    	} 
    	
    }
    

    现在本人来通过这个类编写一个 确定图形类 ——“Circle类”:

    Circle.java:

    package com.mec.about_abstruct;
    
    public class Circle extends BaseShape {
    	private double radius;
    	
    	public Circle() {
    	}
    	
    	public Circle(String name) {
    		super(name);
    		this.type = "圆";
    	}
    	
    	public Circle(String name, double radius) {
    		this(name);
    		this.radius = radius;
    	}
    
    	@Override
    	public double area() {
    		return  Math.PI * radius * radius;
    	}
    
    	@Override
    	public double rounder() {
    		return 2 * Math.PI * radius;
    	}
    
    }
    

    现在同学们可能就对抽象类有了进一步了解:
    抽象类:将类似的东西的共同部分(toString() 及 name 和 type)实现,将不同的、但必须要完成的(area()、rounder() 及 各图形特有尺度)表现出来,但不实现。

    现在本人来对 Test类 进行一些改动:
    Test类:

    package com.mec.about_abstruct.test;
    
    import com.mec.about_abstruct.BaseShape;
    import com.mec.about_abstruct.Circle;
    
    public class Test {
    
    	public static void main(String[] args) {
    		circleOne = new Circle("地球", 6371000.0);
    		System.out.println(circleOne.toString() + "周长= " + circleOne.rounder());
    		System.out.println(circleOne.toString() + "面积= " + circleOne.area());
    	}
    
    }
    

    我们现在来看看运行结果:
    在这里插入图片描述现在,本人来总结下抽象类的注意点

    注意点:

    1. 只要含抽象方法,就是抽象类,就要加上“abstract”修饰符;
    2. 抽象类不能存在对象,因为它存在未实现的方法;
    3. 抽象类中不能存在private类成员及方法,所有抽象方法不能用static修饰;
    4. 抽象类派生的所有非抽象类,那么,
      派生出来的非抽象类必须实现这个抽象类中的所有抽象方法;
      若未实现,则子类也为抽象类,必须加上“abstract”修饰符;

    我们能够发现,无论是 “继承” 还是 “抽象类” ,都是为了 “代码复用”。而本人在本专栏第一篇博文中就讲过,Java最主要的特点就是“面向对象”,也就是“面向工具”,我们现在来实现下一个有趣的问题——计算房价:

    我们只需改动一下上面的代码:

    BaseShape.java:

    package com.mec.about_abstruct.shape;
    
    public abstract class BaseShape {	//只要含抽象方法,就是抽象类,就要加上“abstract”修饰符
    	protected String name;
    	protected String type;
    	//据了解:深圳近3年房价一平最低100
    	protected double price = 100;
    	
    	protected BaseShape() {
    	}
    	
    	protected BaseShape(String name) {
    		this.name = name;
    	}
    	
    	public double getPrice() {
    		//所有的抽象方法,都可以在本类中被非静态方法调用
    		return price * area();
    	}
    	
    	//这两行代码,就是“抽象方法”,不在本类中实现,是专门用来给子类实现的
    	public abstract double area();	
    	public abstract double rounder();
    	
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public String getType() {
    		return type;
    	}
    
    	public void setType(String type) {
    		this.type = type;
    	}
    
    	@Override
    	public String toString() {
    		return name;
    	} 
    	
    }
    

    因为一般租的房子是投影式长方形的,所以本人现在来编写一个 长方形类:
    Rectangle.java:

    package com.mec.about_abstruct.shape;
    
    public class Rectangle extends BaseShape {
    	private double width;
    	private double height;
    	
    	public Rectangle() {
    	}
    
    	public Rectangle(String name) {
    		super(name);
    		this.type = "长方形";
    	}
    	
    	public Rectangle(String name,double width, double height) {
    		this(name);
    		this.height = height;
    		this.width = width;
    	}
    
    	public double getWidth() {
    		return width;
    	}
    
    	public void setWidth(double width) {
    		this.width = width;
    	}
    
    	public double getHeight() {
    		return height;
    	}
    
    	public void setHeight(double height) {
    		this.height = height;
    	}
    	
    	@Override
    	public double area() {
    		return  width * height;
    	}
    
    	@Override
    	public double rounder() {
    		return 2 * (width + height);
    	}
    	
    }
    

    Test.java:

    package com.mec.about_abstruct.test;
    
    import com.mec.about_abstruct.shape.BaseShape;
    import com.mec.about_abstruct.shape.Rectangle;
    
    public class Test {
    
    	public static void main(String[] args) {
    		BaseShape rectangleOne = new Rectangle("深圳一间小房间", 6, 6);
    		System.out.println(rectangleOne.toString() + "周长= " + rectangleOne.rounder());
    		System.out.println(rectangleOne.toString() + "面积= " + rectangleOne.area());
    		System.out.println(rectangleOne.toString() + "房价/月 约= " + rectangleOne.getPrice( ));
    	}
    
    }
    

    在这里插入图片描述

    二、货币类:

    因为本人在上文中已经将“抽象类”的基本知识点都已讲解完毕,那么,在这个例子中,本人就不会再做过多解释,以展示使用方法为目的,为同学们加深这个知识点的印象。
    Currency类(抽象类):

    package com.mec.about_abstruct.currency;
    
    public abstract class Currency {
    	protected String goodsName;
    	protected double weight;
    	
    	//以下是人民币分别对应其他货币的汇率
    	public static double RMB = 1.0;
    	public static double DOLLAR = 0.1459;
    	public static double EURO = 0.1250;
    	public static double POUND = 0.1110;
    	public static double YEN = 16.3797;
    	public static double WON = 163.8141;
    	
    	public Currency(String goodsName, double weight) {
    		this.goodsName = goodsName;
    		this.weight = weight;
    	}
    
    	public double getWeight() {
    		return weight;
    	}
    
    	public abstract double price();
    	
    	public void setWeight(double weight) {
    		this.weight = weight;
    	}
    	
    	public double value(double currencyType) {
    		return price() * currencyType;
    	}
    	
    	//这个方法调用了抽象方法,并将其返回值作为货币转换的基础数据
    	public String getValueString(double currencyType) {
    		return weight + "克" + goodsName + "价格为:"
    				+ value(currencyType)
    				+ currencyName(currencyType);
    	}
    	
    	public String  currencyName(double currencyType) {
    		if(Math.abs(currencyType - DOLLAR) < 1e-6) {
    			return "美元";
    		}
    		if(Math.abs(currencyType - EURO) < 1e-6) {
    			return "欧元";
    		}
    		if(Math.abs(currencyType - YEN) < 1e-6) {
    			return "日元";
    		}
    		if(Math.abs(currencyType - WON) < 1e-6) {
    			return "韩元";
    		}
    		if(Math.abs(currencyType - POUND) < 1e-6) {
    			return "英镑";
    		}
    		
    		return "人民币";
    	}
    	
    }
    

    Silver 类:

    package com.mec.about_abstruct.currency;
    
    public class Silver extends Currency{
    
    	public Silver(double weight) {
    		super("白银", weight);
    	}
    
    	@Override
    	public double price() {
    		return 3.12 * weight;
    	}
    
    }
    

    Gold 类:

    package com.mec.about_abstruct.currency;
    
    public class Gold extends Currency {
    	
    	public Gold(double weight) {
    		super("黄金", weight);
    	}
    
    	@Override
    	public double price() {
    		return 264.5 * weight;
    	}
    
    }
    

    测试类(Demo 类):

    package com.mec.about_abstruct.currency;
    
    public class Demo {
    
    	public static void main(String[] args) {
    		Gold gold = new Gold(1.47);
    		System.out.println(gold.getValueString(Currency.RMB));
    		System.out.println(gold.getValueString(Currency.DOLLAR));
    		System.out.println(gold.getValueString(Currency.POUND));
    		
    		System.out.println("下面演示白银兑换率:");
    		Silver silver = new Silver(132.0);
    		System.out.println(silver.getValueString(Currency.EURO));
    		System.out.println(silver.getValueString(Currency.WON));
    		System.out.println(silver.getValueString(Currency.YEN));
    	}
    
    }
    

    下面本人来展示下运行结果:
    在这里插入图片描述

    由以上代码运行结果的展示,我们大致能够看出:
    抽象类的成员具有如下特点

    抽象类的成员特点

    • 成员变量:
      既可以是变量,也可以是常量。
    • 构造方法:
      必须有,因为 要用于子类访问父类数据的初始化
    • 成员方法:
      既可以是抽象的,也可以是非抽象的。

    抽象类的成员方法具有如下特性

    抽象类的成员方法特性:

    • 抽象方法
      强制要求子类做的事情
    • 非抽象方法
      子类继承的事情,提高代码复用性

    抽象类和继承的逻辑顺序是相反的。
    并且,抽象类 与 本人下一篇博文—— 《内部类 与 匿名内部类》 还有很深的关系,能够看出,这个知识点还是蛮重要的,所以,希望同学们能够加以重视。

  • 相关阅读:
    bzoj4804
    bzoj2962
    bzoj4827
    bzoj2553
    bzoj3611
    BZOJ 1636: [Usaco2007 Jan]Balanced Lineup
    BZOJ 1635: [Usaco2007 Jan]Tallest Cow 最高的牛
    BZOJ 1634: [Usaco2007 Jan]Protecting the Flowers
    BZOJ 1631: [Usaco2007 Feb]Cow Party
    BZOJ 2582: [Usaco2012Jan]Bovine Alliance
  • 原文地址:https://www.cnblogs.com/codderYouzg/p/12418343.html
Copyright © 2011-2022 走看看