java小白训练营day06-OOP:面向对象+封装+继承+多态

Posted 长安紫薯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java小白训练营day06-OOP:面向对象+封装+继承+多态相关的知识,希望对你有一定的参考价值。

面向对象

是一种编程思想,编写程序时如何下手,怎么去解决实际问题。

面向过程和面向对象的区别?

OPP Procedure Oriented Programming 早期编程是思想推崇面向过程的思考(c语言、pascal语言)
OOP Object Oriented Programming 现今主流的编程思想推崇面向对象的思考(c++、java、python、c#)

案例:把大象装入冰箱

面向过程的思考方式:
把一个大的问题拆分成多个小问题,按步骤完成。
步骤:
1)把冰箱门打开
2)把大象放入
3)把冰箱门关上
面向过程的思考,关注处理问题的过程。

面向对象的思考方式:
1)找对象(实体、名词)大象和冰箱
2)分析大象的特质(大耳朵,小尾巴,粗腿)和行为(走,扇耳朵),分析冰箱的特质(容量、温度)和行为(开门、关门)
3)把冰箱门打开,把大象放入,把冰箱门关上

面向过程和面向对象的思考问题方式不同,面向过程关注过程,步骤;面向对象关注实体(对象)对象行为

案例:我周日去超市买葡萄、水饺

面向对象方式思考:
1)找实体(名称)
创建所有的商品的实例-建模(建立模型)(葡萄、水饺、面包、小青菜、菠菜、豆腐。。。。500种)
2)具体买葡萄、水饺

面向对象非常麻烦,它要花大量时间去构建目前来说无用的实体
这样做有什么意义呢?

需求变了,老婆说了,她想吃椰蓉面包
此时面向过程是无法适应的,它之前只关心之前的需要中的内容,只有葡萄、水饺,没有面包。怎么解决?重新设计。
面向对象,之前已经对“面包”进行了建模。这时面向对象的优点就体现了,需要变化了。但是我们只需少量改动即可使用。

面向过程的思考,速度快,更加贴近实际开发。(按需而动)
面向对象的思考,速度慢,构建对象是(实体)想的多想的全,当需求发生变化(需求变更),面向过程就需要改大量的代码,甚至推到重来。工作量巨大,时间没了。面向对象需求变更就小(设计者能力)(按事务发展经验之谈)

实际中开设按面向对象设计,然后按面向过程的设计。这样不是设计过度。两种设计思想相结合。

面向对象的三大特征

封装、继承、多态

封装 encapsulation

隐藏对象的细节
案例:手机
我们不知道手机是如何工作的,它如何去拨打电话就能和别人连线,如果把点信号转换成声音呢?。。。这些细节我们都不知道,但我们照样可以使用手机。
怎么拨号,怎么上网wifi
这些细节都被包装起来,而这些包装的内容对于使用者不用知道。它关心怎么拨号,怎么上wifi,聊微信,聊QQ
封装就是把用户不需要关心的内容进行隐藏,这有什么好处呢?用户关心的内容越少越好,使用起来就越方便。

案例:开车
你懂发动机吗?你懂轮胎型号吗?你懂加油有什么要注意的吗?
都不懂,只懂开车,方向盘,油门,刹车。

java语言中如何体现封装

1)把类的属性(特质、特征)变成私有,不允许直接访问 private 私有
Phone phone = new Phone();
phone.key 按钮,
phone.call() 拨打电话
2)设置get 获取和set方法 设置

不标准的写法

package cn.tedu.entity;
//entiy 就叫实体

/*
 * 创建一个类Phone,体现封装
 * 1)私有属性
 * 2)对应get和set放
 * 私有属性不允许外界直接访问,只能通过对应get和set方法访问
 */
public class Phone {
	public String key;	//按键
	
	//在类中利用main方法进行测试
	public static void main(String[] args) {
		//创建对象实例,才可以调用它的属性
		Phone phone = new Phone(); //创建对象
		phone.key = "136";
		System.out.println(phone.key);
	}
}

package cn.tedu.entity;

/*
 * 体现java中封装,
 * 私有key不允许直接访问(隐藏)
 * 只能通过get和set方法进行操作
 */
public class Phone {
	private String key;
	//自动产生get和set方法,里面会有this,含义

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		//this代表当前对象,this.key代表属性,key代表参数
		this.key = key;
	}
}

package test;

import cn.tedu.entity.Phone;

public class TestPhone {
	public static void main(String[] args) {
		//1.创建实例
		Phone phone = new Phone();
		
		//2.调用set方法设置值
		phone.setKey("188");
		
		//3.调用get方法获取,打印
		System.out.println( phone.getKey() );
	}
}

package cn.tedu.entity;

import java.util.Date; //必须选择util包下的,不能选择sql包下的,否则报错

public class Person {
	//私有属性(字段)都习惯使用包装类型
	private String name;
	private Integer age;
	private Date birthday;	//日期类型
	private String address;
	
	//产生它的gets/sets方法
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	
	@Override //重写,重新父类Object.toString方法
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", birthday=" + birthday + ", address=" + address + "]";
	}
}

package test;

import java.util.Date;

import cn.tedu.entity.Person;

public class TestPerson {
	public static void main(String[] args) {
		//1.创建对象
		Person person = new Person();

		//2.设置值,初始化,设置是没有顺序的(自由)
		person.setName("陈晨");
		person.setAge(12);
		person.setBirthday(new Date());  //当前日期
		person.setAddress("北京中关村");
		
		//3.访问,打印。覆盖它的toString() 自动产生
		System.out.println(person.toString());
	}
}

继承 inheritance

c语言的继承非常强大,它支持多继承(爸、妈。。。)有风险,非常难控制,继承层级过多后,非常难知道继承来自谁
java语言简化c语言,不支持多继承,只支持单继承。安全。

java中继承的类,称为超类superClass(),也称为父类,有时叫基类。
它虽然不支持多继承,但是支持多级继承,多重继承。B继承A,C继承B,也就是说C间接继承A
爸继承了爷财产,我继承爸财产,也就是说,我最终继承了爷爷财产

java有两种继承方式

父类(类 class)使用 extends 关键字(继承)
父类(接口 interface) 使用 implements 关键字(实现)

继承的语法

package cn.tedu.entity;

//代表父类
public class Dad {
	private Double money = 100.0;  //遗产

	public Double getMoney() {
		return money;
	}
	public void setMoney(Double money) {
		this.money = money;
	}
}

package test;

import cn.tedu.entity.Son;

public class TestSon {
	public static void main(String[] args) {
		//需求:看儿子有多少钱?
		//1.创建子类
		Son son = new Son();
		
		//2.通过子类去调用父类方法
		//子类没有,就去访问父类的方法
		System.out.println(son.getMoney());
	}
}

没有继承代码怎么写?

需求:动物类,老虎 tiger(吃eat()、跑run()),鹰 eagle(吃eat()、飞fly())
类有共性eat(),个性,tiger.run()跑、eagle.fly()飞
怎么在java中体现上面的内容。

package cn.tedu.entity;

//老虎类
public class Tiger {
	//共有的方法
	public void eat() {
		System.out.println("吃肉肉");
	}
	
	//个性的方法
	public void run() {
		System.out.println("陆地之王,跑的快");
	}
}

package cn.tedu.entity;

//老鹰类
public class Eagle {
	//共有的方法
	public void eat() {
		System.out.println("吃肉肉");
	}
	
	//个性的方法
	public void fly() {
		System.out.println("天空之王,飞的高");
	}
}

没有使用继承时,代码有冗余,每个类中都有这部分公用的代码,如果代码需要修改,就被迫得修改多处。
它的缺点。
可以使用继承来修改它,改造它!
1)创建父类,公用的代码写 Animal动物类,eat()
2)使用extends继承,去掉重复代码 Tiger extends Animal,Eagle extends Animal。子类可以调用父类的方法

父类的方式

package cn.tedu.entity;

//把老虎和老鹰共性的内容提取到这个类中
public class Animal {
	//共有的方法
	public void eat() {
		System.out.println("吃肉肉");
	}
}

package cn.tedu.entity;

//老虎类,继承父类,动物类
public class Tiger extends Animal{
	//个性的方法
	public void run() {
		System.out.println("陆地之王,跑的快");
	}
}

package cn.tedu.entity;

//老鹰类,继承父类,动物类
public class Eagle extends Animal{
	//个性的方法
	public void fly() {
		System.out.println("天空之王,飞的高");
	}
}

package test;

import cn.tedu.entity.Eagle;
import cn.tedu.entity.Tiger;

public class TestAnimal {
	public static void main(String[] args) {
		//老虎类
		//1.创建对象
		Tiger tiger = new Tiger();
		
		//2.调用对象共性和个性方法
		tiger.eat(); 	//继承父类方法
		tiger.run(); 	//本类个性方法
		
		//老鹰类
		Eagle eagle = new Eagle();
		eagle.eat();	//继承父类方法
		eagle.fly();	//本类个性方法
	}
}

接口方式继承

package cn.tedu.entity;

//水果类,它是一个接口
/*
 * 接口和实现类它不同的地方,实现类中是有实现代码的eat()方法
 * 但是接口中没有,它只有方法的定义,没有方法的实现
 * 也就是说,接口只用来规范你要有什么方法,但是方法子类去具体实现
 */
public interface IFruit {
	public void eat();	//只有放到的定义(声明),没有实现
}

package cn.tedu.entity;

//接口的实现类
//它要实现接口的所有的方法和自己个性方法
public class AppleImpl implements IFruit{

	@Override //重写接口的方法,实现接口的方法
	public void eat() {
		System.out.println("水果可以吃");
	}
	
	//个性方法自己加
	public void cut() {	//削皮
		System.out.println("苹果削皮");
	}
}

package cn.tedu.entity;

//实现类,实现水果接口
public class BeanImpl implements IFruit{

	@Override //实现接口定义方法
	public void eat() {
		System.out.println("吃豆豆");
	}
	
	public void grow() { //添加个性的方法
		System.out.println("种豆豆");
	}
}

package test;

import cn.tedu.entity.AppleImpl;
import cn.tedu.entity.BeanImpl;
import cn.tedu.entity.IFruit;

public class TestFruit {
	public static void main(String[] args) {
		//1、创建对象:接口 实例名=new 子类();
		//AppleImpl apple = new AppleImpl();
		//只能调用接口中声明的方法
		IFruit apple = new AppleImpl();
		
		//2、调用
		apple.eat();
		
		IFruit bean = new BeanImpl();
		bean.eat();
	}
}

两种继承方式的区别

多态 polymorphism

多态:同一个对象同一个方法表现状态不同。
水,绝对零度下-273°(固态),平时温度(液态)

java在多时它一般有一个前提,继承之后发生。
1)子类覆盖Object的toString()方法,重写override,把父类的方法重新定义,运行时多态
2)基本类型的判别 int、byte、short。。。,相同的方法名,但是它的参数类型不同,重载overload,编译器多态

重写,运行时多态

package cn.tedu.entity;

//创建学生类,重新它的toString方法
public class Student {
	//私有属性
	private Integer sno;	//学号
	private String name;	//学生姓名
	private String school;	//毕业学校
	private String address;	//地址
	
	//生成get和set方法
	public Integer getSno() {
		return sno;
	}
	public void setSno(Integer sno) {
		this.sno = sno;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSchool() {
		return school;
	}
	public void setSchool(String school) {
		this.school = school;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	
	@Override
	public String toString() {
		return "Student [sno=" + sno + ", name=" + name + ", school=" + school + ", address=" + address + "]";
	}
}

package test;

import cn.tedu.entity.Student;

public class TestStudent {
	public static void main(String[] args) {
		Student student = new Student();
		
		student.setSno(100);
		student.setName("王琪");
		student.setSchool("清北");
		student.setAddress("五道口");
		
		//同样是一个toString方法,但由于重写后,和重新前表现形式不同,多态
		//什么时候确定呢?父类和子类都有toString方法,此时运行到这里,那调用哪个方法呢?
		//上面是动态选择的,所以称为运行时多态。
		System.out.println(student.toString()); //最终调用子类方法,就近原则
	}
}

重载,编译期多态

package test;

//需求:给定某个8基本类型,声明一个变量,打印出变量的类型
public class TestType {
	//重载,方法名相同,参数类型不同
	public void println(byte x) {
		System.out.println("byte类型");
	}

	public void println(short x) {
		System.out.println("short类型");
	}

	public void println(int x) {
		System.out.println("int类型");
	}

	public void println(long x) {
		System.out.println("long类型");
	}

	public void println(float x) {
		System.out.println("float类型");
	}

	public void println(double x) {
		System.out.println("double类型");
	}
	public void println(char x) {
		System.out.println("char类型");
	}
	public void println(boolean x) {
		System.out.println("boolean类型");
	}

	public static void main(String[] args) {
		//double x = 100.0;
		//char x = 'a';
		boolean x = true;

		// 1.创建类对象实例
		TestType tt = new TestType();

		// 2.调用方法,设置值
		// 编译时,x已经知道它的类型了,称作编译期多态
		// 多态,同一个方法同一个参数,但是结果却不同
		tt.println(x); // 强制设置100为字节类型
	}
}

以上是关于java小白训练营day06-OOP:面向对象+封装+继承+多态的主要内容,如果未能解决你的问题,请参考以下文章

java小白训练营day06-面向对象:封装+继承+多态

202105小白训练营-day04 流程控制

java小白训练营2109-day03-数据结构:基本类型+包装类型+数组+对象

java小白训练营day03-数据结构:基本类型+包装类型+数组+对象

java小白训练营day03-知识回顾

java小白训练营day03-数据结构:jUnit+基本类型+包装类型+数组+对象