Java基础之面向对象的三大特征

面向对象的三大特征

1. 封装
2. 继承
3. 多态

1.封装

思想
将一个事物进行包装,提供对外使用的方法
概念
尽可能隐藏对象的内部实现细节,控制对象的修改及访问的权限
优点
1.保护内部
2.方便使用
3.降低耦合度(解耦合)
是不是感觉有点晦涩难懂?其实我们已经接触过了封装,它也并没有想象中的那么高大上,我们经常会使用到封装的思想。比如,方法(函数),类,包,项目的创建,一个个功能模块的划分就是利用了封装的思想。

2.继承

1.思想
真是生活中的继承,获得长辈存留的事物
代码中的继承,是类与类之间行为(方法)和特征(属性)的一种赠予和获得。
2.继承关键字以及语法
关键字:extends
语法:

访问权限修饰符	class	子类名		extends	父类名{}
//例如
public class Dog extends Animals{}

我们发现这似乎就是我们在创建类的时候加的代码,只是加了extends 和父类的名字。
和现实生活中一样,代码里的继承也是晚辈(子类)继承自己的长辈(父类)
3.特点
1.子类拥有父类的所用属性与方法
2.子类只能拥有一个直属父类(直接继承的父类),但是可以多级继承,属性和方法逐级增加(父类它自己还有它的父类可对应于现实生活中,儿子,父亲,爷爷依次类推)
3.产生继承关系后,子类可以使用父类中的属性和方法,也可以定义子类独有的属性和方法
4.父类
父类就是根据多个类,进行共性的抽取,从而定义的类
例如:
在这里插入图片描述
狗、鱼、鸟、蛇,都拥用一些相同的属性和方法,那么如果在每个类里都重新定义一遍,是不是很傻?所以我们抽取这些属性和方法,把它们封装到一个动物类里,其他的类继承动物类,这样狗、鱼、鸟、蛇,就继承了动物类的属性和方法,从而提高代码的复用性和可扩展性。
而后狗、鱼、鸟、蛇,又都拥有自身独有的一些方法,所以在继承动物类的属性和方法后,再对自身独有的属性和方法进行定义就好了。
注1.所有类都有父类,2.如果没有明确写出所继承的父类,那么默认继承于Object(“祖宗类”)
5.不可使用
也有的地方称为不可继承,但是经过实验后,我们会发现其实已经继承了,但是没有访问的权限,所以这在,我们叫它不可使用
1.构造函数不可直接使用
2.使用private修饰的方法或属性不可直接使用
(private,访问权限修饰符的一种,仅本类可见)
3.父子类不在同一个包里且由默认权限修饰符(default)修饰的属性和方法不可直接使用
(default,访问权限修饰符的一种,仅本包可见)
实验:
父类Animals,name为private修饰,但是加了get,set方法

public class Animals {
	private String name;

	public Animals() {
		System.out.println("这里是Animals类的无参构造函数");
	}
	
	public Animals(String name) {
		System.out.println("这里是Animals类的有参构造函数");
		this.name = name;
	}
	
	public String getName() {
		return name;
	}

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

}

子类:继承父类

public class Cat extends Animals{
	public Cat() {
		super();
	}
	public Cat(String name) {
		super(name);
	}
}

测试类

public class Text {
	public static void main(String[] args) {
		Cat cat1 = new Cat();
		Cat cat2 = new Cat("Tom");
		System.out.println(cat1.getName());
		System.out.println(cat2.getName());
	}
}

执行结果:
在这里插入图片描述

我们可以发现,name虽然是private修饰的,但是我们使用了get和set方法可以继承name属性
6.访问权限修饰符

本类 同包 非同包子类 其他
private × × ×
default × ×
protected ×
public

public:当前项目皆可使用,可以修饰类
protected:同一个包或继承关系中可以使用,不可以修饰类
default:同一个包中可以使用,可以修饰类
private:只能在当前类中使用,不可以修饰类

7.重写与重载

重写 重载
在继承关系中,子类方法与父类方法 在同一个类中
访问权限修饰符(范围)只能变大或不变 访问权限修饰符不管 (可以相同,可以不同)
返回值类型相同 返回值类型不管(可以相同,可以不同)
方法名相同 方法名相同
形参列表相同 形参列表不同

8.super和this
上面的代码里,我们发现了super,那么它的作用是什么呢?它的功能和this相似,同时我们也来复习一下this的作用。
this:调用本类的构造函数,调用本类方法,调用本类属性,区分成员变量和局部变量
super:调用父类构造函数,调用父类的方法(谁调用super所在的方法,super就表示他的父类对象)
注:super和this调用构造函数时,要放在构造函数内的首行,如果super和this同时存在,super在this之前
9.继承后对象的创建过程

  1. new开辟内存空间
  2. 加载父类
  3. 加载子类
  4. 调用父类构造函数
  5. 调用子类构造函数
  6. 赋值给变量(如果没有赋值,则这一步不执行)

3.多态

1.思想
在现实生活中,多态就是一个事物的多种形态,怎么解释呢?比如你在老师面前你是学生,在领导面前你是员工,在父母面前你是孩子,但是你就是你,你没变。
那么映射到代码中,多态就是,不同的类的对象对同一个消息做出的响应,即同一个消息可以根据发送对象的不同而采取多种不同行为的方式。
2.多态存在的条件
1.要有继承
2.要有重写
3.父类对象引用指向子类对象
3.多态的转型
多态的转型分为向上转型和向下转型两种
向上转型(装箱)
父类引用中保存真实子类对象称为向上转型(多态的核心概念)
语法:

父类类型  变量名 = new  子类对象();

向下转型(拆箱)
将父类引用中的真实子类对象,强转回子类本身类型,称为向下转型
语法:

子类类型  变量名 = (子类类型) 父类类型的变量

注:向下转型时,需要强转,且如果父类引用中的子类对象类型和目标类型不匹配,会报错,ClassCastException(类型转换异常)
4.instanceof关键字
判断该对象是否属于该类
语法

变量名  instanceof  类名

注:该表达式是boolean类型的,如果该对象属于该类,返回true,不属于返回false
该关键字常用于向下转型前。
5.实例
之前在网上看到一个很厉害的例子,如果大家把它搞懂的话,对多态的理解就差不多了。

//题目相关的类
public class A {
	public String show(D d) {
		return("A and D");
	}
	public String show(A a) {
		return("A and A");
	}
}
public class B extends A{
	public String show(B b) {
		return("B and B");
	}
	public String show(A a) {
		return("B and A");
	}
}
public class C extends B{
}
public class D extends B{
}
	//问题
	public static void main(String[] args) {
		A a1 = new A();  
        A a2 = new B();  
        B b = new B();  
        C c = new C();   
        D d = new D();   
    1.    System.out.println(a1.show(b));     
    2.    System.out.println(a1.show(c));   
    3.    System.out.println(a1.show(d));    
    4.    System.out.println(a2.show(b));    
    5.    System.out.println(a2.show(c));    
    6.    System.out.println(a2.show(d));    
    7.    System.out.println(b.show(b));     
    8.    System.out.println(b.show(c));    
    9.    System.out.println(b.show(d));        
	}
//答案
1.		A and A
2.		A and A
3.		A and D
4.		B and A
5.		B and A
6.		A and D
7.		B and B
8.		B and B
9.		A and D

这是为什么呢?我们来分析一波
a1是A类对象,比较清晰,不用特别的分析,a1的两个方法:

	public String show(D d) {
		return("A and D");
	}
	public String show(A a) {
		return("A and A");
	}

1 . a1是A类对象,所以只拥有A类的两个show方法,但是参数b是B类对象,A类的两个对象的参数没有B的,但是B类又继承A 类,所以b也可以说是A类对象,所以使用show(A a)的方法
2 . 同理,C类继承B类,B类又继承A类,一级一级判断,所以show(A a)的方法
3 . 这里A类中已经存在了参数为D类对象的方法,所以直接就使用了show(D d)的方法
我们先对a2分析一波
a2使用了多态,向上转型,它本身是B类对象,想要转型成A类对象,(我们可以认为a2本身是B类对象,但是要假装A类对象)所以它只拥有B类对象的方法,但是呢,假装就要装的像一点,B类对象有的,A类没有的,它没法使用(不然就露馅了),所以它只有show(A a)一个方法,然后B类对象又继承A类对象,所以A类对象的方法它也可以使用,A类中也有一个show(A a)方法,两个show(A a)用哪个?因为B继承了A,B类对A的方法进行了重写,所以使用B类的show(A a)方法,这时a2的两个方法就是:

	public String show(A a) {
		return("B and A");
	}
	public String show(D d) {
		return("A and D");
	}

4 . 经过上面的分析,知道a2的方法后,因为参数b继承A类,所以返回B and A
5 . 同理,参数c继承B类,B类又继承A类,所i有返回B and A
6 . d为D类对象,调用show(D d)方法
对b进行分析
b是B类对象,拥有B类对象的两个方法,B类继承A类,b也拥有A类的两个方法,B类对A类的show(A a)方法进行了重写,所以b就有三个方法

	public String show(D d) {
		return("A and D");
	}
	public String show(B b) {
		return("B and B");
	}
	public String show(A a) {
		return("B and A");
	}

7 . b是B类对象,直接调用show(B b)方法
8 . c继承B类,到这就可以直接调用show(B b)方法了(继承是逐级继承的)
9 . d是D类对象,直接调用show(D d)方法

到这就结束了,写的比较乱,希望大家谅解,送大家一句话:咖啡虽苦,但能提神。

猜你喜欢

转载自blog.csdn.net/qq_43336579/article/details/107917195