八.面向对象三大特性
1.封装
一.封装
基本义:把物体打包装到箱子里,然后封起来。
引申义:把一系列功能打包到一台设备里,提供使用这些功能的界面。
概念:将一系列相关事物共同的属性和行为提取出来,放到一个类中,隐藏对象的属性与实现细节,仅对外
提供公共的访问方式。
公共访问方式就指的是get和set方法。
常见的封装体:汽车,电脑,洗衣机
好处:提高安全性,提高复用性,将复杂的事情简单化。
关键:不能让类中的方法直接访问其他类的数据(属性),程序仅通过对象的方法与对象的数据进行交互。
Java中哪些内容体现了封装呢?
在方法中,调用者不知道方法的具体实现(也就是底层);方法可以被重复使用;将繁多的代码以一个方
式呈现,仅通过调用方法就可以实现功能,代码维护也变得简单。
在类中,调用者不知道类的具体实现(安全性),类的对象可以被重复使用,类的对象包含了更多的功能,
使用起来也方便。
A;在本类成员变量中添加private修饰后,测试类中将不能直接访问。
B:由于private的特性,需要在本类中添加访问该属性的方法,供其它类调用。
C:属性的操作一般都是取值和赋值,所以添加对应的公共方法:
getXxx() setXxx(参数)
D:在测试类中通过getXxx()和setXxx(参数)方法来实现属性的访问。
2.JavaBean标准代码
一.定义(标准代码:JavaBean)
Java语言编写类的标准规范。符合JavaBean标准的类,必须是具体的,公共的,并且具有无参数的
构造方法,提供用来操作成员变量的set和get方法。
package Winter.class1;
/***
* Java语言编写类的标准规范。符合JavaBean标准的类,必须是具体的,公共的,并且具有无参数的
* 构造方法,提供用来操作成员变量的set和get方法。
* 定义一个标准的JavaBean类
*/
public class JavaBean01 {
public int getAge(int age) {
return age;
}
public void setAge(int age) {
this.age = age;
}
private int age;
public String getName(String name) {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
public int getScore(int score) {
return score;
}
public void setScore(int score) {
this.score = score;
}
private int score;
public JavaBean01() {}
public JavaBean01(int age, String name, int score) {
this.name = name;
this.age = age;
this.score = score;
}
public void study() {
System.out.println(age + "岁的" + name +"考了" + score + "分");
}
}
//测试类
public class JavaBeanTest01 {
public static void main(String[] args) {
//通过空参创建对象
JavaBean01 s = new JavaBean01();
s.setAge(22);
s.setName("cyl");
s.setScore(88);
s.study();
//
JavaBean01 s1 = new JavaBean01(23,"melody",88);
s1.study();
}
}
3.继承
一.Java中的继承
让类与类之间产生父子关系,被继承的类叫做父类(基类),继承的类叫做子类(派生类)
格式(extends)
class 父类 {
//......
}
class 子类 extends 父类 {
//......
}
效果:子类拥有了父类的非私有成员(成员变量,成员方法)
使用场景:多个类中存在相同的属性和行为时,可以将这些内容提取出来放大一个新类中,让这些类和新类产生父子关系,实现代码复用。
二.继承的缺点:
打破了封装性,高耦合性(类与类之间的相互依赖性)
程序的设计原则:高内聚,低耦合
耦合:两个或多个模块相互依赖于对方
内聚:模块内部结构紧密,独立性强
三.继承关系中类成员的使用
继承关系中子父类成员变量的使用
访问父类变量的方式:super.父类变量名;(super是当前对象父类的引用,是父类内存空间的标识)
对象初始化的顺序:先初始化父类内容,再初始化子类内容。
四.this和super的区别
this的本质是对象(从本类开始找)。
super的本质是父类内存空间的标识(从父类开始找)。
五.继承关系中子父类成员方法的使用
调用父类方法:super.父类成员方法名();
定义重名方法的前提:父类不能满足需求,扩展父类功能;重新实现父类功能。
六.继承关系中子父类构造方法的使用
创建子类对象时,会优先调用父类构造方法
因为在子类构造方法的第一行,隐含语句super();用于调用父类的默认无参构造。如果父类没有无参构造,手动调用
父类其他构造。(可以通过super.(参数);来访问)
子类创建对象时,必须先初始化该对象的父类内容。
七.继承的特点
单继承:Java只支持单继承,但支持多层(重)继承。
Java支持接口的多继承,语法为:接口A extends 接口B,接口C......
只能继承父类的非私有成员(成员变量,成员方法)
构造方法不能被继承(构造方法用于初始化本类对象)
package Winter.inherit;
//父类
/**
* 四大权限修饰符:
* 本类 本包 不同包下的子类 不同包下的无关类
* private 可
* 默认 可 可
* protected 可 可 可
* public 可 可 可 可
*
* summary:
* private 给自己使用。
* 默认:给同包的使用。
* protected:给子类使用(与包的位置无关)。
* public:给所有使用。
* */
public class Father05 {
private void show1() {
System.out.println("private");
}
void show2() {
System.out.println(" ");
}
protected void show3() {
System.out.println("protected");
}
public void show4() {
System.out.println("public");
}
public static void main(String[] args) {
Father05 f1 = new Father05();
f1.show1();
f1.show2();
f1.show3();
f1.show4();
}
}
//子类
public class Son05 extends Father05 {
public static void main(String[] args) {
Father05 f1 = new Father05();
//f1.show1();
f1.show2();
f1.show3();
f1.show4();
Son05 son = new Son05();
son.show2();
son.show3();
son.show4();
}
}
//测试类
public class Test05 {
public static void main(String[] args) {
Father05 f1 = new Father05();
//f1.show1();
f1.show2();
f1.show3();
f1.show4();
}
}
4.方法重写
一.方法重写(Override)
定义:子类中出现和父类方法定义相同的方法的现象(方法的复写,覆盖)
方法名,参数列表,返回值类型都相同
注意事项:父类的私有方法无法重写
子类方法访问权限不能小于父类方法
子类不能比父类抛出更大的异常
使用场景:扩展父类功能
父类功能过时,重新实现父类功能
Java中四大权限修饰符(从小到大):
private 默认(什么都不写) protected public
二.方法重写和重载的区别:
重载(Overload) 重写(Override)
方法名: 相同 相同
参数列表: 不同(个数与位置) 相同
返回值类型: 无关 相同
修饰符: 无关 访问权限不小于被重写方法
定义位置: 同一个类 子父类中
package Winter.class1;
/**
*方法重载
* (1)方法名相同
* (2)参数列表不同(类型,个数,顺序)
* (3)与返回值,修饰符,变量名无关
*/
public class Overload01 {
public void show(){
System.out.println("无参方法");
}
public void show(int num){
System.out.println("有参方法"+num);
}
public void show (String name){
System.out.println("有参方法"+name);
}
public void show(int num,String name){
System.out.println("1:"+num+"2:"+name);
}
public void show(String name,int num){
System.out.println("1:"+name+"2:"+num);
}
//测试类
public class OverloadTest01 {
public static void main(String[] args) {
//创建对象
Overload01 o1 = new Overload01();
o1.show(12);
o1.show("melody");
o1.show(200,"melody");
o1.show("melody",200);
}
}
5.多态
一.多态(polymorphic)
概念:多种状态,同一对象在不同情况下表现出不同的状态或行为。
实现多态的步骤:
要有继承(或实现)关系
要有方法重写
父类引用指向子类对象
eg:
public class Test {
public static void main(String[] args){
//父类引用指向子类对象
Animal a1 = new Dog();
}
}
父类型变量作为参数时,可以接收任意子类对象。
二.多态关系中成员变量的使用
成员变量不能重写
三.多态的好处和弊端
好处:可维护性(仅需维护父类代码,提高了代码的复用性,降低维护代码的工作量)
可扩展性(屏蔽了不同子类对象的差异,实现了向后兼容)
弊端:不能使用子类特有成员(当需要使用子类特有功能时,需要进行类型转换)
类型转换:
1.向上转型(自动类型转换)
子类型转换成夫类型
Animal a1 = new Dog;
2.向下转型(强制类型转换)
父类型转换成子类型
Dog d1 = (Dog)a1;(括号中是目标转换形式)
注意事项:
1.只能在继承层次内进行转换(ClassCastException)
2.将父类对象转换为子类对象之前,使用instance of进行检查
//1.
package Winter.polymorphic;
//父类
public class Animal01 {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Animal01() {
}
public Animal01(String name) {
this.name = name;
}
private String name;
//成员方法
public void eat() {
System.out.println("吃饭");
}
}
//子类
public class Dog01 extends Animal01{
//因为各种动物吃的都不一样,所以要优化eat();方法
@Override
public void eat() {
System.out.println(getName()+"吃骨头");
}
}
//测试类
/**
* 动物类案例:
* 已知父类Animal,成员变量为:姓名;成员方法为:eat();方法
* 有一个子类Dog,试模拟多态
* */
public class Test01 {
public static void main(String[] args) {
//演示多态
/**
* 实现多态的步骤:
* 要有继承(或实现)关系
* 要有方法重写
* 父类引用指向子类对象
* */
//多态
Animal01 dog = new Dog01();//父类引用指向子类对象,编译看左,运行看右
//测试成员方法的调用
dog.setName("melody");
dog.eat();
}
}
//2.
package Winter.polymorphic;
//父类
public class Animal02 {
public Animal02() {
}
public Animal02(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
//成员方法:
public void eat() {
System.out.println("吃饭");
}
}
//子类1
public class Dog02 extends Animal02{
@Override
public void eat() {
System.out.println(getName()+"吃骨头");
}
}
//子类2
public class Mouse02 extends Animal02{
@Override
public void eat() {
System.out.println(getName()+"吃大米");
}
}
//测试类
/**
* Dog02和Mouse02都继承了Animal02类
*/
public class Test02 {
public static void main(String[] args) {
Dog02 d1 =new Dog02();
d1.setName("melody");
showAnimal(d1);
Mouse02 m = new Mouse02();
m.setName("melody");
showAnimal(m);
}
//在该类中定义showAnimal();方法(多态做法)
/**
* 多态的使用场景:
* 父类型可以作为形参的数据类型
* 这样可以接受其任意的子类对象
* */
public static void showAnimal(Animal02 d) {
d.eat();
}
}
//3.
package Winter.polymorphic;
//父类
public class Animal03 {
String name = "animal";
}
//子类
public class Dog03 extends Animal03 {
String name = "dog";
}
/***
* 多态关系中成员变量的使用
*
* 结论:
* 多态关系中,成员变量不涉及重写
* 使用成员变量遵循编译看左,运行看左
* 使用成员方法遵循编译看左,运行看右
*/
public class Test03 {
public static void main(String[] args) {
//通过多态的方式创建对象
//父类引用指向子类对象
Animal03 a1 = new Dog03();
System.out.println(a1.name);//animal
}
}
//4.
package Winter.polymorphic;
//父类
public class Animal04 {
public void eat() {
System.out.println("吃饭");
}
}
//子类
public class Dog04 extends Animal04{
@Override
public void eat() {
System.out.println("吃骨头");
}
//子类特有的方法
public void watch() {
System.out.println("会看家");
}
}
//测试类
/**
* 类型转换:
* 1.向上转型(自动类型转换)
* 子类型转换成夫类型
* Animal a1 = new Dog;
* 2.向下转型(强制类型转换)
* 父类型转换成子类型
* Dog d1 = (Dog)animal;(括号中是目标转换形式)
* 注意事项:
* 1.只能在继承层次内进行转换(ClassCastException)
* 2.将父类对象转换为子类对象之前,使用instance of进行检查
* */
public class Test04 {
public static void main(String[] args) {
//通过多态创建对象,调用子类成员
Animal04 a1 = new Dog04();
//调用eat方法
a1.eat();
//调用watch方法
/* Dog04 d1 = (Dog04)a1;
d1.watch();*/
//优化方案:
//判断当前对象是否是Dog04类的对象,如果是再调用watch方法。
if (a1 instanceof Dog04){//判断a1是否是Dog类的对象
//条件满足
Dog04 d1 = (Dog04)a1;
d1.watch();
}
}
}