java面对对象三大特性封装、继承、多态(详细)

面对对象概述

今天主要分享一下java除语法之外核心的部分——面对对象,之前听过好多小伙伴都说理解不了,调侃面向对象简直是面向深渊,但其实只是一种思想的转变,希望这篇文章可以能让你理解面向对象的这种思想

理解面对对象

  首先面对象,是一种思考的方法,是一种思想,是通过早起的面向过程衍化而来,面对过程:强调的是功能行为面对对象:讲功能封装成对象,强调的是具备功能的对象
  一个很经典的案例,把大象装进冰箱里需要分几个步骤呢,如果按照面向过程的思维方式就是三步:1.把冰箱门打开 2.把大象塞进去 3.关上冰箱门,这里我们强调的是过程,打开动作、存储(塞大象)动作、关闭动作,注重的过程当中涉及的行为,也就是功能,那如果按照面对对象的思想就是:打开、存储、关闭都是冰箱的一个行为,也就是说我们只需要操作冰箱具备的功能就可以了,我们就把这些功能定义在冰箱当中,冰箱就是一个实实在在存在的东西,我们就称之为——对象,现在再去看,就已经不是打开、存储和关闭了,而是一个事物——冰箱本身,而冰箱就已经具备了,打开、存储和关闭,也就是说,有了冰箱,就有了这些功能,看下图
在这里插入图片描述
左边(面对过程)强调的是打开、存储和关闭的动作,而右边(面对对象)强调的就是对象本身,这样做会把复杂的事情变得简单化,面向过程的话需要注重好多的动作,而面向过程我们只需要注重一个事物,那就是对象本身,从一个执行者(面对过程)的角色,变成了一个指挥者(面对对象)

类和对象的关系

讲解面对对象需要围绕面对对象的三大特征:封装、继承、多态来讲解,在下文这些特征都会依次讲解,请耐心阅读
类:java语言用来描述事物的一种方法,对现实中生活事物的一种描述
对象:这类事物实实在在存在的个体

  举个栗子:比如一个男人和一个女人,我们需要来描述这个对象,那其实男人和女人都是我们现实生活中的事物,描述其实就是对具体对象提取共性的事物,笼统地讲就是对具体事物的一个抽象,也就是说我们只要找到男人和女人的共性事物来描述就可以了,比如男人和女人都是人类,他们都具备吃饭、睡觉、思考的功能,虽然这样描述起来不是很具体,但是这类事物就已经大致描述完了,因为如果要具体描述的话,就要落实到每个人身上,比如每个人都有不同的姓名、年龄、身高、思维方式等。这里的人类就是一个类,具体的每个人就是一个对象。
  将上面的内容映射到java里面,描述就是通过class定义的类,具体对象就是对应java在堆内存中用new建立的对象实体
  现在咱们实战演练一下,小测试:描述一个汽车;

public class Study{
	public static void main(String[] args){
		//生产汽车,通过new操作符来完成
		Car c = new Car();//产生一个汽车对象c 这个对象就已经具备了颜色和轮胎数量
		//讲已有的车的颜色改成蓝色,指挥对象使用,指挥方式:对象名.成员
		c.color="blue"; 
		c.run();//输出内容
	}
}

//类的概念可以理解为是车的设计图纸
//对象的概念就是每一辆生产出的车
//定义类就是在描述事物,就是在描述属性和行为
//而属性和行为就是类中的成员 成员变量和成员方法
class Car{
	//描述汽车的颜色
	String color = "red";
	//轮胎数量
	int nums = 4;
	//行为(行为对应的是一个方法)
	void run(){
		System.out.println("颜色:"+color+"---轮胎数量:"+nums);
	}
}

面对对象三大特性之——封装

概念&案例

  封装是指隐藏对象的属性和实现细节,仅对外提供公共的访问方式,便于使用,提高重用性和安全性
方法就是java中最小的封装体
举个栗子:我有一个编写教程功能是对外提供的,你不用在意我这个功能是怎么实现的,也就是说你看我教程不用知道我是怎么学到的这些知识,你只需要调用我的编写教程的功能,增加一些你的知识量,除此之外我还有打篮球功能,但是我打篮球的这个功能是不对外提供的,也就是说你无法调用的我篮球功能和你打篮球。
老样子,来个经典案例,java中23种设计模式之一的——单例设计模式
一个类里面只允许有一个对象,也就是说多个对象操作的类都是同一个,在堆空间内只有一个实体,保证对象在内存中的唯一性,这种设计模式就是实现了一个类在内存中只有一个对象

public class Study{
	public static void main(String[] args){
		Single s = Single.getInsatance();//使用类名获取静态方法返回的对象
	}
}
//首先 禁止其他程序建立对象 
//让其他程序可以访问到类对象 ,所以在本类中,自定义一个对象
//为了方便其他程序对自定义对象的访问,对外提供一个访问方式
//代码体现如下
class Single{
	private Single{//构造函数私有化
		//在类中创建一个本类对象
		static Single s = new Single(); //因为下面的静态方法只能访问静态成员,所以static修饰
	}
	//提供一个方法可以获取该对象
	public static getInsatance(){ //因为无法创建对象,所以使用静态用类名创建
		return s;
	}
}	

单例设计模式分为"懒汉式和饿汉式",本演示采用饿汉式,有兴趣的话可以在下面评论,我可以补充懒汉式的内容

面对对象三大特性之——继承

继承需要注意的地方

继承在开发中其实用到的地方相对较多,一般在写代码的时候发现代码中存在重复代码,需要向上抽取的时候,就会考虑到继承,但稍有不注意也会引起很大的问题,继承是一把双刃剑,要慎用,所以继承需要注意以下事项:

  • 单一继承性(在Java中是不支持多继承的,通俗的说子类只能有一个父类,而父类可以有很多子类,但接口和接口之间是支持多继承的,接口概念会在接下来的教程里面讲解)
  • 支持多层继承(继承可以一直传下去,子类有父类,父类又有父类)
  • 如果父类成员使用private修饰,那么子类不能被继承(private修饰符,代表被修饰的内容只在本类有效)
  • 如果一个子类继承了父类的属性和方法还可以有自己特有的属性和方法(不光有父类的属性(可继承的)和方法(可继承的),也有自己独有的属性和方法)
  • 当子类和父类的成员变量重名的时候,子类优先

案例

先看下面定义的两个类,一个是学生(student),一个是工人(worker),写完后发现,这两个类是有一些共性的内容,比如学生和工人都拥有姓名和年龄,是不是有种方法可以让我们把这些共性内容定义在一个单独的类里,然后让我们的这两个类和它产生一些关系,然后让学生和工人类都具备这些特征,这就是向上抽取的过程
在这里插入图片描述
这就是我们的第二个概念了,继承(extends),这个就能够让学生和工人对 人(Person)这个类产生关系,学生和工人就是人这个 类的子类,人就是这个学生类的父类/超类/基类,子继承父,所以他们就可以共用人的特征,姓名和年龄
在这里插入图片描述
很显而易见了,继承:

  • 提高了代码的复用性
  • 提高了扩展性
  • 提高了可维护性
  • 让类和类之间产生了关系(才有了多态的概念,多态会在下文讲到)
    在这里插入图片描述
    注意事项:千万不要为了获取其他类的功能简化代码乱使用继承功能,必须是类和类之间有所属关系(is a)才可以继承

面对对象三大特性之——多态

概念

多态是指某一种事物存在多种形态,可以理解为事物存在的多种体现形态,比如用第一个案例的“人”来表示,人就可以分为,男人和女人,这其实就是人这类事物的不同体现形态,动物同样也有多种形态,例如猫和狗

猫 m = new();
//猫也是动物
动物 m = new();
//m这个实体既具备猫的类型,也具备动物的类型
//前提是猫必须是动物的一种(继承关系)

除了这种体现,其实在方法的重载覆盖上也体现了多态性(重载和覆盖讲在未来的教程里讲解,这里仅作了解),这里我主要讲解的是对象的多态性
这里会围绕着多态的表现形式,多态的前提,多态的好处,多态如何应用讲解

案例

首先看下面代码:
在这里插入图片描述

按照之前逻辑肯定是这样做
Cat c = new Cat();
c.eat()
Dog d = new Dog();
d.eat();

这样做的话,如果我想让另一只猫吃东西,就要多创建另外一个对象,然后再调用eat()方法,这句话就在重复使用了,我们就可以封装方法

public static void main(String[] args){
Cat c = new Cat();
func (c) ;
}
//定义一个方法,提高代码复用性
//注意:这里还没有涉及到多态
public void func(Cat c){
c.eat();
}

现在又出现一个问题,狗该怎么使用这个方法呢,有没有一种办法让参数传进去之后就可以显示出当前传递的对象呢?
在这里插入图片描述
这种重载方式当然也可以实现,但是如果后面的类型较多的时候,例如出现了猪、牛、羊等等等等,那时候该怎么办呢?
这就涉及到转化了,猫除了具备猫类型以外,他还继承了动物,他也是动物的一种,如果用Animal来做这个事情,也是可以的

public static void main(String[] args){
Cat c = new Cat();
func( c);
}
//定义一个方法,提高代码复用性
public void func(Animal a){
a.eat();//打印 -> 小鱼干
}

这就是一个对象具备的多种形态造成的
多态的体现:
父类的引用指向了自己的子类对象/父类的引用也可以接收自己的子类对象
多态的好处
多态大大提高了程序的扩展性
前提
必须是类和类之间存在关系(继承或实现)

转型

向上转型和向下转型
从基本数据类型我们能够看出:向上转型是可以自动完成的;向下转型是需要强制转换的,引用数据类型也是如此
还用刚刚的例子:

//因为猫是动物,所以这里自动转型(向上转型是可以自动完成的)
		Animal a = new Cat();//类型提升(向上转型) 把猫提升成了动物

刚刚演示了向上转型,下面演示一下向上转型

Animal a = new Cat();
//强制将父类的引用转成子类类型
Cat c = (Cat) a;
c.shout();// 输出 -> 喵喵

在这里插入图片描述
这里有种转换方式需要注意一下:
不要出现下面的这种操作,将父类对象转换成子类类型
我们能转换的是父类应用指向了自己的子类对象时,该应用可以被提升/转换
多态自始至终都是子类对象在变化

Animal a = new Animal();
Cat c = new (Cat)a;

案例代码附上:

public class Study{
	public static void main(String[] args){
		//因为猫是动物,所以这里自动转型(向上转型是可以自动完成的)
		Animal a = new Cat();//类型提升(向上转型) 把猫提升成了动物
		Cat c = (Cat)a;
		c.eat();
	}
	
	public void func(Animal a){
		a.eat();
	}
	
}
class Animal{//这里可以修改成抽象类abstract更加形象
	public void eat(){
		
	}
}
class Cat extends Animal{
	public void eat(){
		System.out.print("小鱼干");
	}
	public void shout(){
		System.out.print("喵喵");
	}
}

class Dog extends Animal{
	public void eat(){
		System.out.print("骨头/屎");
	}
	public void shout(){
		System.out.print("汪汪");
	}
}

总结:

Java里面的每定义一个类实际上就相当于一种新的数据类型,就跟int ,float, String等一样,不过是一种新定义的类型而已
文章内如有讲解不清晰不理解或者不对的地方可以在评论区指出,看到一定改正,最后,感谢阅读!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章