**思考：** 构造方法能作为抽象方法吗？

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

"去商场买衣服"，这句话描述的是一个抽象的行为∶到底去哪个商场买衣服，是实体店还是网店，买什么样的衣服，是短衫、裙子，还是其他的什么衣服?在"去商场买衣服"这句话中，并没有为"买衣服"这个抽象行为指明一个确定的信息。设计一个商场的抽象类，并在其中定义买东西的抽象方法，具体是什么商场、买什么东西，交给子类去实现即可。代码如下∶
```java
public abstract class Market {
	public String name; // 商场名称
	public String goods; // 商品名称

	public abstract void shop(); // 抽象方法，用来输出信息
}
```
定义一个TaobaoMarket类，继承自 Market 抽象类，实现其中的shop()抽象方法:
```java
public class TaobaoMarket extends Market {
	public void shop() {
		System.out.println(name + "网购" + goods);
	}
}
```
定义一个 WallMarket 类，继承自Market 抽象类，实现其中的shop()抽象方法:
```java

public class WallMarket extends Market {
	public void shop() {
		System.out.println(name + "实体店购买" + goods);
	}
}
```
定义一个 GoShopping类，在该类中分别使用WallMarket类和TaobaoMarket类创建抽象类的对象，并分别给抽象类中的成员变量赋不同的值，调用 shop()方法分别输出结果:
```java
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（图形）类，该类中有一个计算面积的方法。圆形和矩形都继承自图形类，输出圆形和矩形的面积。

#### 练习2：
创建工厂类，工厂类中有一个抽象的生产方法，创建汽车厂和鞋厂类，重写工厂类中的抽象生产方法，输出汽车厂生产的是汽车，鞋厂生产的是鞋。

 
     


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


## 实例2：通过实现接口 绘制出特殊的平行四边形
特殊的平行四边形有矩形、正方形和菱形。现使用接口的相关知识绘制出特殊的平行四边形。
```java

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():
```java
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();
	}
}



```

**思考：**
如何区分抽象类和接口？有哪些不同？