java 12 练习题:抽象类与接口

思考: 构造方法能作为抽象方法吗?

文章目录

    • 实例1:使用抽象类模拟"去商场买衣服"场景
        • 练习1:
        • 练习2:
    • 实例2:通过实现接口 绘制出特殊的平行四边形
    • 实例3: 使用继承输出儿子喜欢做的事

实例1:使用抽象类模拟"去商场买衣服"场景

“去商场买衣服”,这句话描述的是一个抽象的行为∶到底去哪个商场买衣服,是实体店还是网店,买什么样的衣服,是短衫、裙子,还是其他的什么衣服?在"去商场买衣服"这句话中,并没有为"买衣服"这个抽象行为指明一个确定的信息。设计一个商场的抽象类,并在其中定义买东西的抽象方法,具体是什么商场、买什么东西,交给子类去实现即可。代码如下∶

public abstract class Market {
	public String name; // 商场名称
	public String goods; // 商品名称

	public abstract void shop(); // 抽象方法,用来输出信息
}

定义一个TaobaoMarket类,继承自 Market 抽象类,实现其中的shop()抽象方法:

public class TaobaoMarket extends Market {
	public void shop() {
		System.out.println(name + "网购" + goods);
	}
}

定义一个 WallMarket 类,继承自Market 抽象类,实现其中的shop()抽象方法:


public class WallMarket extends Market {
	public void shop() {
		System.out.println(name + "实体店购买" + goods);
	}
}

定义一个 GoShopping类,在该类中分别使用WallMarket类和TaobaoMarket类创建抽象类的对象,并分别给抽象类中的成员变量赋不同的值,调用 shop()方法分别输出结果:

public class GoShopping {
	public static void main(String[] args) {
		Market market = new WallMarket(); // 使用派生类对象创建抽象类对象
		market.name = "沃尔玛";
		market.goods = "七匹狼西服";
		market.shop();
		market = new TaobaoMarket(); // 使用派生类对象创建抽象类对象
		market.name = "淘宝";
		market.goods = "韩都衣舍花裙";
		market.shop();
	}
}
练习1:

创建 Shape(图形)类,该类中有一个计算面积的方法。圆形和矩形都继承自图形类,输出圆形和矩形的面积。


public class Circle extends Shape {
	double radius;
	
	public Circle(double radius) {
		this.radius = radius;
	}

	@Override
	public double getArea() {
		return Math.PI * this.radius * this.radius;
	}
}



public class Rectangle extends Shape {
	double length;
	double width;

	public Rectangle(double length, double width) {
		this.length = length;
		this.width = width;
	}

	@Override
	public double getArea() {
		return this.length * this.width;
	}
}



public abstract class Shape {
	String name;
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public abstract double getArea();
}



public class Test {
	public static void main(String[] args) {
		Circle circle = new Circle(1.5);
		circle.name = "圆形";
		System.out.println(circle.name + "面积:" + circle.getArea());
		Rectangle rectangle = new Rectangle(5.5, 2);
		rectangle.name = "矩形";
		System.out.println(rectangle.name + "面积:" + rectangle.getArea());
	}
}

练习2:

创建工厂类,工厂类中有一个抽象的生产方法,创建汽车厂和鞋厂类,重写工厂类中的抽象生产方法,输出汽车厂生产的是汽车,鞋厂生产的是鞋。


public class AutoPlant extends Factory {
	String productsName;
	
	public AutoPlant(String productsName) {
		this.productsName = productsName;
	}

	@Override
	public String produce() {
		return this.productsName;
	}
}



public abstract class Factory {
	String name;
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public abstract String produce();
}



public class ShoeFactory extends Factory {
	String productsName;
	
	public ShoeFactory(String productsName) {
		this.productsName = productsName;
	}
	
	@Override
	public String produce() {
		return this.productsName;
	}
}



public class Test {
	public static void main(String[] args) {
		AutoPlant autoPlant = new AutoPlant("汽车");
		autoPlant.setName("汽车厂");
		System.out.println(autoPlant.getName() + "生产的是" + autoPlant.productsName);
		ShoeFactory shoeFactory = new ShoeFactory("鞋");
		shoeFactory.setName("鞋厂");
		System.out.println(shoeFactory.getName() + "生产的是" + shoeFactory.productsName);
	}
}

使用抽象类和抽象方法时,需要遵循以下原则

  • 在抽象类中,可以包含抽象方法,也可以不包含抽象方法,但是包含了抽象方法的类必须被定义为抽象类。
  • 抽象类不能直接被实例化,即使抽象类中没有声明抽象方法,也不能被实例化。
  • 抽象类被继承后,子类需要重写抽象类中所有的抽象方法。
  • 如果继承抽象类的子类也被声明为抽象类,则可以不用重写父类中所有的抽象方法。使用抽象类时,可能会出现这样的问题;程序中会有太多冗余的代码,同时父类的局限性很大。例如,上面的例子中,也许某个不需要 shop()方法的子类也必须重写 shop()方法。如果将这个 shop()方法从父类中拿出,放在别的类里,又会出现新间题∶某些类想要实现"买衣服"的场景,意然需要继承两个父类。Java中规定,一个类不能同时继承多个父类,为解决这种问题,接口应运而生。

实例2:通过实现接口 绘制出特殊的平行四边形

特殊的平行四边形有矩形、正方形和菱形。现使用接口的相关知识绘制出特殊的平行四边形。


interface DrawImage { // 定义“画图形”接口
	public void draw(); // 定义抽象方法“画”
}

class Rectangle implements DrawImage { // 矩形类实现了drawTest接口
	public void draw() { // 矩形类中实现draw()方法
		System.out.println("画矩形");
	}
}

class Square implements DrawImage { // 正方形类实现了drawTest接口
	public void draw() { // 正方形类中实现draw()方法
		System.out.println("画正方形");
	}
}

class Diamond implements DrawImage { // 菱形类实现了drawTest接口
	public void draw() { // 菱形类中实现draw()方法
		System.out.println("画菱形");
	}
}

public class SpecialParallelogram { // 定义特殊的平行四边形类
	public static void main(String[] args) {
		// 接口也可以进行向上转型操作
		DrawImage[] images = { new Rectangle(), new Square(), new Diamond() };
		// 遍历“画图形”接口类型的数组
		for (int i = 0; i < images.length; i++) {
			images[i].draw(); // 调用draw()方法
		}
	}
}

提醒: 由于接口中的方法都是抽象方法,所以当子类实现接口时,必须实现接口中的所有抽象方法。

实例3: 使用继承输出儿子喜欢做的事

爸爸喜欢做的事有抽烟和钓鱼,妈妈喜欢做的事有看电视和做饭,儿子完全继承了爸爸妈妈的爱好,使用多重继承输出儿子喜欢做的事。首先定义一个DadLikeDo接口,并在接口中定义两个方法 smoke()和 fish():

public interface DadLikeDo { // 定义“爸爸喜欢做的事”接口
	void smoke(); // 抽烟的方法

	void fish(); // 钓鱼的方法
}

public interface MomLikeDo { // 定义“妈妈喜欢做的事”接口
	void watchTV(); // 看电视的方法

	void cook(); // 做饭的方法
}


// 继承DadLikeDo接口和MomLikeDo接口
public class SonLikeDo implements DadLikeDo, MomLikeDo {
	public void watchTV() { // 实现watchTV()方法
		System.out.println("看电视");
	}

	public void cook() { // 实现cook()方法
		System.out.println("做饭");
	}

	public void smoke() { // 实现smoke()方法
		System.out.println("抽烟");
	}

	public void fish() { // 实现fish()方法
		System.out.println("钓鱼");
	}

	public static void main(String[] args) {
		SonLikeDo son = new SonLikeDo(); // 通过子类创建IFather接口对象
		System.out.println("儿子喜欢做的事有:");
		// 子类对象调用DadLikeDo和MomLikeDo两个接口被实现的所有方法
		son.watchTV();
		son.cook();
		son.smoke();
		son.fish();
	}
}



思考:
如何区分抽象类和接口?有哪些不同?

你可能感兴趣的:(Java技术专家,java,开发语言)