Java学习之路(八)类的三大特征

一、封装

封装是什么呢?不扯定义,简单点来说就是将对象的属性以private进行修饰,大家到隐藏的效果,需要调用时,通过高权限的访问权限修饰符(通常是public)定义的方法进行获取与修改。

举个例子,假设定义一个Person类,类中有着age这个属性,数据类型为int整型,那么我们可以通过对象名.age的方式进行调用。

package com.h.test3;

public class TestMain {

	public static void main(String[] args) {
		Person person = new Person();
		person.age = 10;
		System.out.println(person.age);
		
	}

}
package com.h.test3;

public class Person {
	public int age;
	
}

但是,这样是存在隐患的,Int型的变量的范围是-231~231-1,但是age的年龄是不允许为负值的,于是这个时候就要用到封装了。

封装的实现步骤:

  1. 修改属性的可见性(访问权限修饰符)
  2. 创建getter / setter方法
  3. 在getter / setter方法中加入属性控制语句
package com.h.test3;

public class TestMain {

	public static void main(String[] args) {
		Person person = new Person();
		person.setAge(-10);
		System.out.println(person.getAge());	// output: 0
		person.setAge(10);
		System.out.println(person.getAge());	// output: 10
	}

}
package com.h.test3;

public class Person {
	private int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		if (age >= 0) {
			this.age = age;
		}
	}
	
}

PS. 属性不一定需要都设置getter和setter方法,看个人的需求。

二、继承

说到继承,那就得先说一个类:Object,Object是所有类的父类,也就是所有类的老祖宗。

继承的理解其实也不难,可以把它等同于人类Person与学生Student的关系。

首先,我们知道学生一定是人类,但是反过来,人类不一定是学生。那么,在这种情况下,人类就是父类,学生就是子类。在人类的群体中,学生只是一部分,还有一部分可以是教师,可以是公司职员等等,但是不论是学生,还是教师,亦或者公司职员,他们都是人类。

那么,理解了继承后,我们来看看继承是如何实现的:

  1. 编写父类
  2. 编写子类,使用extends关键字继承父类
package com.h.test3;

public class Person {
	private int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		if (age >= 0) {
			this.age = age;
		}
	}
	
}
package com.h.test3;

public class Student extends Person{
	private String studentID;

	public String getStudentID() {
		return studentID;
	}

	public void setStudentID(String studentID) {
		this.studentID = studentID;
	}

}

package com.h.test3;

public class TestMain {

	public static void main(String[] args) {
		Person person = new Person();
		person.setAge(10);
		System.out.println(person.getAge());	// output: 10
		
		Student student = new Student();
		student.setAge(15);		
		System.out.println(student.getAge());	// output: 15
		student.setStudentID("Stu01");
		System.out.println(student.getStudentID());	// output: Stu01
	}

}

使用类的好处就在于,我们可以避免写重复无意义的代码,只要使用继承,父类所允许子类继承的属性和方法,子类都可以调用。

继承实现后的初始顺序:

e00DMQ.png

package com.h.test3;

public class Person {
	static {
		System.out.println("父类静态代码块");
	}
	
	{
		System.out.println("父类构造代码块");
	}
	
	public Person() {
		System.out.println("父类构造方法");
	}
	
}
package com.h.test3;

public class Student extends Person{
	static {
		System.out.println("子类静态代码块");
	}
	
	{
		System.out.println("子类构造代码块");
	}
	
	public Student() {
		System.out.println("子类构造方法");
	}

}
package com.h.test3;

public class TestMain {

	public static void main(String[] args) {
		Student student = new Student();
	}

}

/* 运行结果如下:
父类静态代码块
子类静态代码块
父类构造代码块
父类构造方法
子类构造代码块
子类构造方法
*/

那么,说完继承,就不得不提一下方法的重写与重载。

针对方法的重写与重载,有这么一张表格:

重载重写
有效范围同一个类中有继承关系的子类中
方法名相同相同
参数列表不同(参数顺序,个数,类型)相同(参数顺序,个数,类型)
返回值任意相同,允许不同,但必须为子类
访问修饰符任意访问范围大于等于父类的访问范围
参数名无关无关

举例如下:

package com.h.test3;

public class Person {
	
	public void methodOverload() {
		System.out.println("父类重载无参");
	}
	
	public void methodOverload(String str) {
		System.out.println("父类重载带参");
	}
	
	public void methodOverride() {
		System.out.println("父类未重写");
	}
	
}

package com.h.test3;

public class Student extends Person{
	
	@Override
	public void methodOverload() {
		System.out.println("子类重写无参");
	}

	@Override
	public void methodOverride() {
		System.out.println("子类重写");
	}
}

package com.h.test3;

public class TestMain {

	public static void main(String[] args) {
		Person person = new Person();
		Student student = new Student();
		
		student.methodOverload();		// output: 子类重写无参
		student.methodOverload("1");	// output: 父类重载带参
		student.methodOverride();		// output: 子类重写

		person.methodOverload();		// output: 父类重载无参
		person.methodOverload("1");		// output: 父类重载带参
		person.methodOverride();		// output: 父类未重写
	}

}

三、多态

说起类的三大特征,封装、继承都很理解,也很容易理解,但是要说起多态,那似乎就变得有点抽象了起来,但尽管如此,多态却还是类的三个特征中最为重要的那一个。

什么是多态呢?多态是指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。

我们可以举个例子,比如动物的叫声,首先动物是一个父类,猫和狗都是一个继承于动物父类的一个子类,动物有一个方法:叫,这时根据“叫”这个行为,猫和狗的表现是不一样的,这就是多态。

实现多态有着3个必要条件:

  • 继承
  • 重写
  • 向上转型(父类引用指向子类对象)
package com.h.test3;

public class Animal {
	public void say() {
		System.out.println("神秘的叫声");
	}
}

package com.h.test3;

public class Cat extends Animal {
	@Override
	public void say() {
		System.out.println("喵喵");
	}
}
package com.h.test3;

public class Dog extends Animal {
	@Override
	public void say() {
		System.out.println("汪汪");
	}
}
package com.h.test3;

public class TestMain {

	public static void main(String[] args) {
		Animal animal = new Animal();
		animal.say();	// output: 神秘的叫声
		
		animal = new Cat();
		animal.say();	// output: 喵喵
		
		animal = new Dog();
		animal.say();	// output: 汪汪
	}

}

从案例上我们可以看出,同一个对象animal,其指向的对象引用不同,那么对于重写的方法say()上来说,其所表现的形式也就不同,也就是说,animal的say()方法的表现形式由实例化对象决定。

既然说到了向上转型,那我们再来说说向下转型。向上转型是将父类引用指向子类对象,那么向下转型反过来就是将子类引用指向父类对象。

向上转型向下转型
意义父类引用指向子类对象子类引用指向父类对象
举例Father f = new SonSon s = (Son) f;

举个例子:

package com.h.test3;

public class Animal {
	public void say() {
		System.out.println("神秘的叫声");
	}
}
package com.h.test3;

public class Cat extends Animal {
	@Override
	public void say() {
		System.out.println("喵喵");
	}
	
	public void eatFish() {
		System.out.println("猫吃鱼");
	}
}
package com.h.test3;

public class Dog extends Animal {
	@Override
	public void say() {
		// TODO Auto-generated method stub
		System.out.println("汪汪");
	}
	
	public void eatBone() {
		System.out.println("吃骨头");
	}
}
package com.h.test3;

public class TestMain {

	public static void main(String[] args) {

		Animal animal = new Animal();
		
		// 向上转型
		animal = new Cat();
		animal.say();	// output: 喵喵
        
		// animal = new Dog(); // 转型失败
        
		// 向下转型
		if (animal instanceof Cat) {
			Cat cat = (Cat) animal;
			cat.say();	// output: 喵喵
			cat.eatFish();	// output: 猫吃鱼
		}else {
			System.out.println("转型失败");
		}
		
	}

}

通过上面这案例,我们可以把向上转型和向下转型转换成一个故事来例于理解。

很久以前,有一只猫,它喜欢自己“喵喵”的叫声和吃鱼。有一天,它被某种不知名的力量给改造成了“动物”(向上转型),变成“动物”的它,失去了身为猫时那种喜欢吃鱼的爱好(丢失了子类特有的成员方法与属性),但是幸运的是,它还保有从前那种“喵喵”的叫声(多态)。某天,它突然想吃点什么,听狗说骨头的味道很不错,于是它准备去变成狗去尝尝骨头的滋味,但是它失败了。于是,忍无可忍的它,决定变回猫,结果很显然,它成功了(向下转型),同时,它也找回了身为猫身的那种喜欢吃鱼的爱好,美滋滋地饱餐了一顿。可喜可贺,可喜可贺。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值