第七章 面向对象核心技术总结

本文深入讲解了面向对象编程中的核心概念:封装示例、继承机制(包括extends关键字和方法重写)、多态应用(方法重载与类的上下转型),以及抽象类与接口的区别。通过实例演示,理解类的抽象和接口在设计中的角色。
摘要由CSDN通过智能技术生成

7.1 类的封装

封装是面向对象编程的核心思想,将对象的属性和行为封装起来,其载体就是类。

例7.1

public class Diqizhang {

	public static void main(String[] args) {
		String cookName="Tom Cruise";//厨师的名字叫Tom Cruise
		
		System.out.println("**请让厨师为我做一份香辣肉丝。***");
		System.out.println(cookName + "切葱花");
		System.out.println(cookName + "洗蔬菜");
		System.out.println(cookName + "开始烹饪" + "香辣肉丝");
		
		System.out.println("**请问厨师叫什么名字?***");
		System.out.println(cookName);
		
		System.out.println("**请让厨师给我切一点葱花。***");
		System.out.println(cookName + "切葱花");
}
}

 例7.2

public class Diqizhang {
	public static void main(String[] args) {
		Cook1 cook = new Cook1();// 创建厨师类的对象
		System.out.println("**请让厨师为我做一份香辣肉丝。***");
		cook.cooking("香辣肉丝");// 厨师烹饪香辣肉丝
		System.out.println("**你们的厨师叫什么名字?***");
		System.out.println(cook.name);// 厨师回答自己的名字
		System.out.println("**请让厨师给我切一点葱花。***");
		cook.cutOnion();// 厨师去切葱花
	}
}
 
class Cook1 {
	String name;// 厨师的名字
 
	public Cook1() {
		this.name = "Tom Cruise";// 厨师的名字叫Tom Cruise
	}
 
	void cutOnion() {// 厨师切葱花
		System.out.println(name + "切葱花");
	}
 
	void washVegetavles() {// 厨师洗蔬菜
		System.out.println(name + "洗蔬菜");
	}
 
	void cooking(String dish) {// 厨师烹饪顾客点的菜
		washVegetavles();
		cutOnion();
		System.out.println(name + "开始烹饪" + dish);
}}

 例7.3

public class Diqizhang {
	public static void main(String[] args) {
		Cook2 cook = new Cook2();// 创建厨师类的对象
		System.out.println("**请让厨师为我做一份香辣肉丝。***");
		cook.cooking("香辣肉丝");// 厨师烹饪香辣肉丝
		System.out.println("**你们的厨师叫什么名字?***");
		System.out.println(cook.name);// 厨师回答自己的名字
		System.out.println("**请让厨师给我切一点葱花。***");
		cook.cutOnion();// 厨师去切葱花
	}
}
 
class Cook2 {
	String name;//厨师的名字
 
	public Cook2() {
		this.name = "Tom Cruise";//厨师的名字叫Tom Cruise
	}
 
	void cutOnion() {//厨师切葱花
		System.out.println(name + "切葱花");
	}
 
	private void washVegetavles() {//厨师洗蔬菜
		System.out.println(name + "洗蔬菜");
	}
 
	void cooking(String dish) {//厨师烹饪顾客点的菜
		washVegetavles();
		cutOnion();
		System.out.println(name + "开始烹饪" + dish);
		}
	}

 例7.4

public class Qi {
	private Cook2 cook = new Cook2();// 餐厅封装的厨师类
 
	public void takeOrder(String dish) {// 下单
		cook.cooking(dish);// 通知厨师做菜
		System.out.println("您的菜好了,请慢用。");
	}
 
	public String saySorry() {// 拒绝顾客请求
		return "抱歉,餐厅不提供此项服务。";
	}
 
	public static void main(String[] args) {
		Qi water = new Qi();// 创建餐厅对象,为顾客提供服务
		System.out.println("**请让厨师为我做一份香辣肉丝。***");
		water.takeOrder("香辣肉丝");// 服务员给顾客下单
		System.out.println("**你们的厨师叫什么名字?***");
		System.out.println(water.saySorry());// 服务员给顾客善意的答复
		System.out.println("**请让厨师给我切一点葱花。***");
		System.out.println(water.saySorry());// /服务员给善意的答复顾客
}
}

7.2 类的继承

继承在面向对象开发思想中是一个非常重要的概念,它使整个程序架构具有一定的弹性,在程序中复用已经定义完善的类不仅可以减少软件开发周期,还可以提高软件的可维护性和可扩展性。

7.2.1 extends 关键字

 例7.5

class Computer {// 父类:电脑
	String screen = "液晶显示屏";
 
	void startup() {
		System.out.println("电脑正在开机,请等待...");
	}
}
public class Qi extends Computer {
	String battery = "5000毫安电池";// 子类独有的属性
	public static void main(String[] args) {
		Computer pc = new Computer();// 电脑类
		System.out.println("computer的屏幕是:" + pc.screen);
		pc.startup();
		Qi ipad = new Qi();// 平板电脑类
		System.out.println("pad的屏幕是:" + ipad.screen);// 子类可以直接使用父类属性
		System.out.println("pad的电池是:" + ipad.battery);// 子类独有的属性
		ipad.startup();// 子类可以直接使用父类方法
	}
 
}

 7.2.2 方法的重写

在继承中还有一种特殊的重写方式,子类与父类的成员方法,返回值方法,参数类型及个数完全相同,唯一不同的是方法实践内容,这种特殊重写方式被称为重构。

 例7.6

class Computer2 {// 父类:电脑
 
	void showPicture() {
		System.out.println("鼠标点击");
	}
}
public class Qi extends Computer2{
	void showPicture() {
		System.out.println("手指点击触摸屏");
	}
	public static void main(String[] args) {
		Computer2 pc = new Computer2();// 电脑类
		System.out.print("pc打开图片:");
		pc.showPicture();// 调用方法
 
		Qi ipad = new Qi();// 平板电脑类
		System.out.print("ipad打开图片:");
		ipad.showPicture();// 重写父类方法
 
		Computer2 computerpad = new Qi();// 父类声明,子类实现
		System.out.print("computerpad打开图片:");
		computerpad.showPicture();// 调用父类方法,实现子类重写的逻辑
	}
}

 例7.7

class Computer3 {// 父类:电脑
	String  sayHello(){
		return "欢迎使用";
	}
}
public class Qi extends Computer3{
 
	String sayHello() {// 子类重写父类方法
		return super.sayHello() + "平板电脑";// 调用父类方法,在其结果后添加字符串
	}
 
	public static void main(String[] args) {
		Computer3 pc = new Computer3();// 电脑类
		System.out.println(pc.sayHello());
		Qi ipad = new Qi();// 平板电脑类
		System.out.println(ipad.sayHello());
	}
}

7.2.3 所有类的父类——Object类
在开始学习使用class 关键字定义类时,就应用了继承原理,因为在Java中,所有的类型都直接或间接继承了java.lang.Object类。Object类是比较特殊的类,它是所有类的父类,是Java类层中的最高层类。当创建一个类时,总是在继承,除非某个类已经指定要从其他类继承,否则它就是从java.lang.Object 类继承而来的,可见 Java 中的每个类都源于java.lang.Object 类,如 String、Integer 等类都是继承于 Object 类;除此之外自定义的类也都继承于Object 类。由于所有类都是 Object 子类,所以在定义类时,省略了 extends Object关键字。

例7.8

public class 	Qi {
	public String toString() { 						//重写toString()方法
		return "在" + getClass().getName() + "类中重写toString()方法";
	}
	public static void main(String[] args) {
		System.out.println(new Qi()); 	//打印本类对象
	}
}

 例7.9

class V { // 自定义类V
}
public class Qi {
	public static void main(String[] args) {
		String s1 = "123"; // 实例化两个对象,内容相同
		String s2 = "123";
		System.out.println(s1.equals(s2)); // 使用equals()方法调用
		V v1 = new V(); // 实例化两个V类对象
		V v2 = new V();
		System.out.println(v1.equals(v2)); // 使用equals()方法比较v1与v2对象
	}
}

7.3 类的多态
多态意为一个名字可具有多种语义,在程序设计语言中,多态性是指“一种定义,多种实现”例如,运算符“+”作用于两个整型量时是求和,而作用于两个字符型量时则是将其连接在一起。利用多态可以使程序具有良好的扩展性,并可以对所有类对象进行通用的处理。类的多态性可以从两方面体现:一是方法的重载,二是类的上下转型。

7.3.1 方法的重载
方法的存在就是在同一个类中允许同时存在一个以上的同名方法,只要这些方法的参数个数或类型不同即可。

 例7.10

public class Qi{
	// 定义一个方法
		public static int add(int a) {
			return a;
		}
		// 定义与第一个方法参数个数不同的方法
		public static int add(int a, int b) {
			return a + b;
		}
		// 定义与第一个方法相同名称、参数类型不同的方法
		public static double add(double a, double b) {
			return a + b;
		}
		// 定义一个成员方法
		public static int add(int a, double b) {
			return (int) (a + b);
		}
		// 这个方法与前一个方法参数次序不同
		public static int add(double a, int b) {
			return (int) (a + b);
		}
		// 定义不定长参数
		public static int add(int... a) {
			int s = 0;
			// 根据参数个数循环操作
			for (int i = 0; i < a.length; i++) {
				s += a[i];// 将每个参数的值相加
			}
			return s;// 将计算结果返回
		}
		public static void main(String args[]) {
			System.out.println("调用add(int)方法:" + add(1));//输出
			System.out.println("调用add(int,int)方法:" + add(1, 2));//输出
			System.out.println("调用add(double,double)方法:" + add(2.1, 3.3));//输出
			System.out.println("调用add(int a, double b)方法:" + add(1, 3.3));//输出
			System.out.println("调用add(double a, int b) 方法:" + add(2.1, 3));//输出
			System.out.println("调用add(int... a)不定长参数方法:"+ add(1, 2, 3, 4, 5, 6, 7, 8, 9));//输出
			System.out.println("调用add(int... a)不定长参数方法:" + add(2, 3, 4));//输出
		}
}

 例7.11

class Quadrangle { // 四边形类
	public static void draw(Quadrangle q) { // 四边形类中的方法
		// SomeSentence
	}
}
public class Qi extends Quadrangle{
	public static void main(String args[]) {
		Qi p = new Qi(); // 实例化平行四边形类对象引用
		draw(p); // 调用父类方法
	}}

 例7.12

class Quadrangle {
	public static void draw(Quadrangle q) {
		// SomeSentence
	}
}
public class Qi extends Quadrangle {
	public static void main(String args[]) {
		draw(new Qi());
		// 将平行四边形类对象看作是四边形对象,称为向上转型操作
		Quadrangle q = new Qi();
		Qi p = (Qi) q; // 将父类对象赋予子类对象
		// //将父类对象赋予子类对象,并强制转换为子类型
		//Parallelogram p = (Parallelogram) q;
	}
}

例7.13

class Quadrangle {
		public static void draw(Quadrangle q) {
			// SomeSentence
		}
	}
 
	class Square extends Quadrangle {
		// SomeSentence
	}
 
	class Anything {
		// SomeSentence
	}
public class Qi extends Quadrangle {
	public static void main(String args[]) {
			Quadrangle q = new Quadrangle(); // 实例化父类对象
			// 判断父类对象是否为Parallelogram子类的一个实例
			if (q instanceof Qi) {
				Qi p = (Qi) q; // 进行向下转型操作
			}
			// 判断父类对象是否为Parallelogram子类的一个实例
			if (q instanceof Square) {
				Square s = (Square) q; // 进行向下转型操作
			}
			// 由于q对象不为Anything类的对象,所以这条语句是错误的
			// System.out.println(q instanceof Anything);
		}
}

7.4 抽象类与接口


7.4.1 抽象类与抽象方法

在解决实际问题时,一般将父类定义为抽象类,需要使用这个父类进行继承与多态处理。回想继承和多态原理,继承树中越是在上方的类越抽象,如鸽子类继承鸟类、鸟类继承动物类等。在多态机制中,并不需要将父类初始化对象,我们需要的只是子类对象,所以在Java语言中设置抽象类不可以实例化对象,因为图形类不能抽象出任何一种具体图形,但它的子类却可以。
Java 中定义抽象类时,需要使用 abstract 关键字,其语法如下:                                                          [权限修饰符] abstract class 类名{
类体                                                                                                                                                     } 

 用abstract 关键字定义的类称为抽象类,而使用abstract 关键字定义的方法称为抽象方法,抽象方法的定义语法如下:
[权限修饰符]abstract 方法返回值类型方法名(参数列表);

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

(1)在抽象类中可以包含抽象方法,也可以不包含抽象方法,但是包含了抽象方法的被定位为抽象类

(2)抽象类不能直接实例化,即使抽象类中没有声明抽象方法也不能实例化。

(3)抽象类被继承后,子类需要实现其中所有的抽象方法。

(4)如果继承抽象类的子类也被声明为抽象类,则可以不用实现父类中所有的抽象方法。

例7.14

public interface IMather {
	void watchTV();// 看电视的方法
	void cooking();// 做饭的方法
}
 
 
 
public class TaobaoMarker extends Market {
	    @Override
		public void shop() {
			// TODO Auto-generated method stub
			System.out.println(name+"网购"+goods);
		}
}
 
 
public class WallMarket extends Market {
	@Override
	public void shop() {
		// TODO Auto-generated method stub
		System.out.println(name+"实体店购买"+goods);
	}
}
 
public class Qi {
		public static void main(String[] args) {
			Market market = new WallMarket();// 使用派生类对象创建抽象类对象
			market.name = "沃尔玛";
			market.goods = "七匹狼西服";
			market.shop();
			market = new TaobaoMarker();// 使用派生类对象创建抽象类对象
			market.name = "淘宝";
			market.goods = "韩都衣舍花裙";
			market.shop();
		}
}

例7.15

interface drawTest { // 定义接口
	public void draw(); // 定义方法
}
 
// 定义平行四边形类,该类实现了drawTest接口
class ParallelogramgleUseInterface implements drawTest {
	public void draw() { // 由于该类实现了接口,所以需要覆盖draw()方法
		System.out.println("平行四边形.draw()");
	}
}
 
// 定义正方形类,该类实现了drawTest接口
class SquareUseInterface implements drawTest {
	public void draw() {
		System.out.println("正方形.draw()");
	}
}
public class Qi {
	public static void main(String[] args) {
		drawTest[] d = { // 接口也可以进行向上转型操作
				new SquareUseInterface(), new ParallelogramgleUseInterface() };
		for (int i = 0; i < d.length; i++) {
			d[i].draw(); // 调用draw()方法
		}
}
	}

7.4.3 多重继承‘


 在Java中类不允许多重继承,但使用接口就可以实现多重继承,因为一个类可以同时实现多个接口,这样可以将所有需要实现的接口放置在implements关键字后并使用逗号“”隔开,但这可能会在一个类中产生庞大的代码量,因为继承一个接口时需要实现接口中所有的方法。
通过接口实现多重继承的语法如下:
class 类名 implements 接口1,接口2,…,接口n
例7.16

public interface IMather {
	void watchTV();// 看电视的方法
	void cooking();// 做饭的方法
}
 
 
 
public class H7_16 implements IFather, IMather {// 继承IFather接口和IMather接口
 
	@Override
	public void watchTV() {// 重写watchTV()方法
		System.out.println("我喜欢看电视");
	}
 
	@Override
	public void cooking() {// 重写cook()方法
		System.out.println("我喜欢做饭");
	}
 
	@Override
	public void smoking() {// 重写smoke()方法
		System.out.println("我喜欢抽烟");
	}
 
	@Override
	public void goFishing() {// 重写goFishing()方法
		System.out.println("我喜欢钓鱼");
	}
 
	public static void main(String[] args) {
		IFather father = new Qi();// 通过子类创建IFather接口对象
		System.out.println("爸爸的爱好:");
		// 使用接口对象调用子类中实现的方法
		father.smoking();
		father.goFishing();
		IMather mather = new Qi();// 通过子类创建IMather接口对象
		System.out.println("\n妈妈的爱好:");
		// 使用接口对象调用子类中实现的方法
		mather.cooking();
		mather.watchTV();
	}
 
}

7.4.4 区分抽象类与接口


抽象类和接口都包含可以由子类继承实现的成员,但抽象类是对根源的抽象,而接口是对动抽象。抽象类的功能要远超过接口,那为什么还要使用接口呢?这主要是由于定义抽象类的个高(因为每个类只能继承一个类,在这个类中,必须继承或编写出其子类的所有共性,因此,虽然接口在功能上会弱化许多,但它只是针对一个动作的描述,而且可以在一个类中同时实现多个接这样会降低设计阶段的难度。
抽象类和接口的区别主要有以下几点。
(1)子类只能继承一个抽象类,但可以实现任意多个接口。
(2)一个类要实现一个接口必须实现接口中的所有方法,而抽象类不必。
(3)抽象类中的成员变量可以是各种类型,而接口中的成员变量只能是public static final 的(4)接口中只能定义抽象方法,而抽象类中可以定义非抽象方法。(5)抽象类中可以有静态方法和静态代码块等,接口中不可以。
(6)接口不能被实例化,没有构造方法,但抽象类可以有构造方法。

抽象类与接口的不同

例7.17

public interface IFather {
	void smoking();// 抽烟的方法
 
	void goFishing();// 钓鱼的方法
}
 
 
 
 
public interface IFather {
	void smoking();// 抽烟的方法
 
	void goFishing();// 钓鱼的方法
}
 
 
 
 

public final class Qi {
	int a = 3; 
	void doit() {
	}
	public static void main(String args[]) {
		Qi f = new Qi();
		f.a++;
		System.out.println(f.a);
	}
}

 例7.18

class Parents {
	private final void doit() {
		System.out.println("父类.doit()");
	}
 
	final void doit2() {
		System.out.println("父类.doit2()");
	}
 
	public void doit3() {
		System.out.println("父类.doit3()");
	}
}
 
class Sub extends Parents {
	public final void doit() { // 在子类中定义一个doit()方法
		System.out.println("子类.doit()");
	}
 
	// final void doit2(){ //final方法不能覆盖
	// System.out.println("子类.doit2()");
	// }
	public void doit3() {
		System.out.println("子类.doit3()");
	}
}
public class Qi {
	public static void main(String[] args) {
		Sub s = new Sub(); // 实例化
		s.doit(); // 调用doit()方法
		Parents p = s; // 执行向上转型操作
		// p.doit(); //不能调用private方法
		p.doit2();
		p.doit3();
	}
}

 例7.19

import static java.lang.System.out;
import java.util.Random;
class Test {
	int i = 0;
}
public class Qi {
	static Random rand = new Random();
	private final int VALUE_1 = 9; // 声明一个final常量
	private static final int VALUE_2 = 10; // 声明一个final、static常量
	private final Test test = new Test(); // 声明一个final引用
	private Test test2 = new Test(); // 声明一个不是final的引用
	private final int[] a = { 1, 2, 3, 4, 5, 6 }; // 声明一个定义为final的数组
	private final int i4 = rand.nextInt(20);
	private static final int i5 = rand.nextInt(20);
 
	public String toString() {
		return i4 + " " + i5 + " ";
	}
 
	public static void main(String[] args) {
		Qi data = new Qi();
		//data.test = new Test();
		// 可以对指定为final的引用中的成员变量赋值
		// 但不能将定义为final的引用指向其他引用
		//data.value2++;
		// 不能改变定义为final的常量值
		data.test2 = new Test(); // 可以将没有定义为final的引用指向其他引用
		for (int i = 0; i < data.a.length; i++) {
			// a[i]=9;
			// 不能对定义为final的数组赋值
		}
		out.println(data);
		out.println("data2");
		out.println(new Qi());
		out.println(data);
	}
}

 例7.20

import java.util.Random;
import static java.lang.System.out;
public class Qi {
	private static Random rand = new Random(); // 实例化一个Random类对象
	// 随机产生0~10之间的随机数赋予定义为final的a1
	private final int a1 = rand.nextInt(10);
	// 随机产生0~10之间的随机数赋予定义为static final的a2
	private static final int a2 = rand.nextInt(10);
 
	public static void main(String[] args) {
		Qi fdata = new Qi(); // 实例化一个对象
		// 调用定义为final的a1
		out.println("重新实例化对象调用a1的值:" + fdata.a1);
		// 调用定义为static final的a2
		out.println("重新实例化对象调用a1的值:" + fdata.a2);
		// 实例化另外一个对象
		Qi fdata2 = new Qi();
		out.println("重新实例化对象调用a1的值:" + fdata2.a1);
		out.println("重新实例化对象调用a2的值:" + fdata2.a2);
	}
}

 例7.21

public class 	Qi {
	innerClass in = new innerClass(); // 在外部类实例化内部类对象引用
 
	public void ouf() {
		in.inf(); // 在外部类方法中调用内部类方法
	}
 
	class innerClass {
		innerClass() { // 内部类构造方法
		}
 
		public void inf() { // 内部类成员方法
		}
 
		int y = 0; // 定义内部类成员变量
	}
 
	public innerClass doit() { // 外部类方法,返回值为内部类引用
		// y=4; //外部类不可以直接访问内部类成员变量
		in.y = 4;
		return new innerClass(); // 返回内部类引用
	}
 
	public static void main(String args[]) {
		Qi out = new Qi();
		// 内部类的对象实例化操作必须在外部类或外部类的非静态方法中实现
		Qi.innerClass in = out.doit();
		Qi.innerClass in2 = out.new innerClass();
	}
}

例7.22

interface OutInterface { // 定义一个接口
	public void f();
}
 
public class Qi {
	public static void main(String args[]) {
		OuterClass2  out = new OuterClass2 (); // 实例化一个OuterClass2对象
		// 调用doit()方法,返回一个OutInterface接口
		OutInterface outinter = out.doit();
		outinter.f(); // 调用f()方法
	}
}
 
class OuterClass2  {
	// 定义一个内部类实现OutInterface接口
	private class InnerClass implements OutInterface {
		InnerClass(String s) { // 内部类构造方法
			System.out.println(s);
		}
 
		public void f() { // 实现接口中的f()方法
			System.out.println("访问内部类中的f()方法");
		}
	}
 
	public OutInterface doit() { // 定义一个方法,返回值类型为OutInterface接口
		return new InnerClass("访问内部类构造方法");
	}
}

 例7.23

public class Qi {
	private int x;
	private class Inner {
		private int x = 9;
		public void doit(int x) {
			x++; 					//调用的是形参x
			this.x++; 					//调用内部类的变量x
	        Qi.this.x++; 	//调用外部类的变量x
		}
	}
}

例7.24

public interface Qi {
}
class OuterClass3 {
	public Qi doit(final String x) { // doit()方法参数为final类型
		// 在doit()方法中定义一个内部类
		class InnerClass2 implements Qi {
			InnerClass2(String s) {
				s = x;
				System.out.println(s);
			}
		}
		return new InnerClass2("doit");
	}
}

例7.25

public interface Wi {
}
class OuterClass4 {
		public Wi doit() { // 定义doit()方法
			return new Wi() { // 声明匿名内部类
				private int i = 0;
 
				public int getValue() {
					return i;
				}
			};
		}
}

7.6.4 静态内部类
可以这样认为,普通的内部类对象隐式地在外部保存了一个引用,指向创建它的外部类对象但如果内部类被定义为static,就会有更多的限制。静态内部类具有以下两个特点:
(1)如果创建静态内部类的对象,不需要创建其外部类的对象;
(2)不能从静态内部类的对象中访问非静态外部类的对象。

例7.26

public class Wi {
	int x = 100;
 
	static class Inner {
		void doitInner() {
			// System.out.println("外部类"+x);
		}
 
		public static void main(String args[]) {
			System.out.println();
		}
	}
}

例7.27

public class Wi extends ClassA.ClassB { // 继承内部类ClassB
		public Wi(ClassA a) {
			a.super();
		}
	}
 
	class ClassA {
		class ClassB {
		}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值