面向对象的三大特征

一.封装:

1.概述:

我们日常使用的电脑主机,把CPU、内存、主板等都封装到机箱里面去,假如没有机箱的话,这些会全部散落在一起,开机也没有开机按钮,需要我们直接操作跳线才能把电脑开启。一旦操作不慎会让机器损坏。

(1)如果我们用机箱把它们封装起来,就不需要这样做了,体现了封装的——安全特性

(2)当我们想要给电脑加内存的时候,我们可以直接把电脑给维修的人,等他加好内存之后。我们拿到手的还是那个机箱,里面发生了怎样的变化我们也不知道。体现了封装的——将变化隔离

(3)在机箱里面提供一个开机按钮,而不需要我们直接使用跳线开机,体现了封装的——便于使用

(4)只要机箱提供了开机功能,无论这个机箱拿到哪里去,都可以使用这个开机功能,体现了封装的——提供重复性

2.补充:权限修饰符

权限修饰符就是控制变量的可见范围的。

(1)public:公共的。public修饰的成员变量或者方法任何人都可以直接访问。

(2)private:私有的。private修饰的成员变量或者方法只能在本类中进行直接访问。

3.封装的步骤:

(1)使用private修饰需要被封装的属性。

(2)提供一个公共的方法设置或者获取该私有的成员属性。

        命名规范:

                      set属性名( );

                      get属性名( );

4.封装一定要提供get或者set方法吗?

不一定,要根据需求来定。比如说女性的年龄如果不想对外界显示,那么就不用对外提供get方法。

5.封装的规范:在现实开发中,一般实体类的所有成员属性(成员变量)都要封装起来。

注解:①实体类:实体类就是用于描述一类事物的就称作为实体类。

          ②类大体上可以分为实体类或工具类。

6.封装的好处:

(1)提高数据的安全性。

(2)操作简单。操作简单是相对调用者而言的。

(3)隐藏了实现,调用者不用关心被调用者内部的方法是怎么写的。如果调用这个方法出错,也是被调用者去改代码。

7.实例

需求:使用Java类描述一个计算器类,计算器具有操作数1,操作数2,操作符三个公共的属性,还具备计算的功能行为。要求不能对操作数1,操作数2,运算符这些属性进行直接的赋值,要封装起来。

分析:我们只需要提供set方法即可,不用提供get方法。字符串需要使用"equals",而+、-、*、/是字符,属于基本数据类型,只要使用“==”即可。

class Calculator{
	private int num1;	//操作数1
	private int num2;	//操作数2
	private char option;	//运算符
	
	//提供公共的方法设置属性值……
	public void initCalculator(int n1,int n2,char o){
		num1 = n1;
		num2 = n2;
		if(o == '+'||o == '-'||o == '*'||o == '/'){
			option = o;
		}else{
			option = '+';
		}
	}

	//计算的功能
	public void calculate(){
		switch(option){
			case '+':
				System.out.println("做加法运算,结果是:"+(num1+num2));
				break;
			case '-':
				System.out.println("做减法运算的结果是:"+(num1-num2));
				break;
			case '*':
				System.out.println("做乘法运算的结果是:"+(num1*num2));
				break;
			case '/':
				System.out.println("做除法运算的结果是:"+(num1/num2));
				break;
		}
	}
}

class Demo2{
	public static void main(String[] args){
		//创建了一个计算器对象
		Calculator c = new Calculator();
		//设置属性值
		c.initCalculator(1,2,'+');
		//调用计算器的计算功能
		c.calculate();
	}
}

运行结果如下图所示:


二.继承

1.存在的问题:

(1)如果没有继承,会出现类和类的关系无法描述;

(2)如果没有继承,类和类之间有关系会出现类和类的描述代码的重复;

2.定义:

继承是通过关键字extends体现的,继承可以理解为某种事物是另一种事物的一种;

3.格式:

class 类名1 extends 类名2 {

}

4.继承要注意的事项:
(1) 千万不要为了减少重复代码而去继承,只有真正存在着继承关系的时候才去继承。例如人和狗虽然都有名字,但是他们没有继承关系;
(2) 父类私有的成员不能被继承。现实生活中父亲的东西也不能全部都继承下来,分家的时候也肯定会留下养老金,那些东西是属于他个人的,你不能继承;再比如父亲的年龄如果不用private修饰也是可以继承的,但是年龄是属于他私人的,不能继承就需要用private修饰,用private修饰年龄属性后,子类对象就不能使用了。
(3) 父类的构造函数不能被继承。构造方法是用来初始化这个类的成员属性的,就算子类把它继承下来也没有意义。因为这个功能只有在父类中才有作用;
(4) 创建子类对象时默认会先调用父类无参的构造函数。

5.实例:

class Person{
	String name;
	private	int age;
	public  Person(String name){
		this.name = name;
	}
	public Person(){
		System.out.println("Person类的构造方法被调用了....");
	}
	public void eat(){
		System.out.println(name+"在吃饭...");
	}
}
//学生类
class Student extends Person {  // Student 就称作为Person类的子类, Person类就称作为Student的父类       //(超类、基类)
	int num; //学号
	public Student(){
		System.out.println("Student类的构造方法被调用了....");
	}
	public void study(){
		System.out.println(name+"good good study , day day up");
	}	
}
class Demo1 {
	public static void main(String[] args) {
		Student s = new Student();
		
	}
}

运行结果如下图所示:


6.继承的特点:

(1)描述类和类之间的关系;

(2)降低类和类之间的重复代码;

7.注意:

(1)降低对象和对象之间的代码重复可以使用静态变量,降低类和类之间的代码重复可以使用继承;

(2)父类的构造函数不能被继承,但并不是说父类的构造函数不能被调用,调用和继承是没有任何关系的。

比如说Demo1和Student两个类也没有继承关系,但是在Demo1中new了Student对象后,在Demo1中是可以调用Student类中的方法。

8.调用父类的构造方法是可以初始化从父类继承下去的属性的

三.多态

1.定义:通俗的说多态就是一个对象具备多种形态。专业的说法是:父类的引用类型变量指向了子类的对象,或者是接口的引用类型变量指向了接口实现类的对象。

2.多态的前提:必须存在继承或者实现的关系。

3.多态要注意 的细节:

(1)  多态情况下,子父类存在同名的成员变量(不管是静态还是非静态)时,访问的是父类的成员变量。(如果是普通方式,访问的是子类的)
(2) 多态情况下,子父类存在同名的非静态的成员函数时,访问的是子类的成员函数。(如果是普通方式,访问的是子类的)
(3) 多态情况下,子父类存在同名的静态的成员函数时,访问的是父类的成员函数。
(4) 多态情况下,不能访问子类特有的成员。
和Java编译器的运行原理有关,Java编译器在一编译的时候就会检查这个引用类型变量a所属的这个类Animal是否有指定的成员dig(),如果没有就会马上报错。
普通情况下都是看左边的,只有在非静态函数的情况下才是看右边的。

总结:多态情况下,子父类存在同名的成员时,访问的都是父类的成员,除了在同名非静态函数时才是访问子类的。

4.疑问:为什么不能访问子类特有的成员?

与Java编译器的原理有关,编译看左边,运行不一定看右边

Java编译器在编译的时候,会检查引用类型变量所属的类是否具备指定的成员,如果不具备马上编译报错。

5.实例

//动物类
abstract class Animal{
	String name;
	String  color = "动物色";
	public Animal(String name){
		this.name = name;
	}
	public abstract void run();
	public static void eat(){
		System.out.println("动物在吃..");
	}
}

//老鼠
class  Mouse extends Animal{
	String color = "黑色";
	public Mouse(String name){
		super(name);
	}
	public  void run(){
		System.out.println(name+"四条腿慢慢的走!");
	}
	public static void eat(){
		System.out.println("老鼠在偷吃..");
	}
	//老鼠特有方法---打洞
	public void dig(){
		System.out.println("老鼠在打洞..");
	}
}

class Fish extends Animal {
	public Fish(String name){
		super(name);
	}
	public  void run(){
		System.out.println(name+"摇摇尾巴游..");
	}
}

class Demo1{
	public static void main(String[] args) {
		Animal a = new Mouse("老鼠");//可以理解为别人要一个动物对象,这时候给他一个老鼠,完        //全符合现实中的说法。
		//a.dig();会报错。
		a.eat();
	}	
}

运行结果如下图所示:


6.多态的应用:
(2) 多态用于返回值类型的时候,可以返回更多类型的数据。

(1) 多态用于形参类型的时候,可以接收更多类型的数据 。(需求1)

7.多态的好处:提高了代码的拓展性。

8.实例一

(1) 需求:定义一个函数可以接收任意类型的图形对象,并且打印图形面积与周长。

(2) 实例

//图形类
abstract class MyShape{
	public abstract void getArea();
	public abstract void getLength();	
}

class Circle extends MyShape{
	public static final double PI = 3.14;
	double r;
	public Circle(double r){
		this.r =r ;	
	}
	public  void getArea(){
		System.out.println("圆形的面积:"+ PI*r*r);
	}
	public  void getLength(){
		System.out.println("圆形的周长:"+ 2*PI*r);
	}
}

class Rect  extends MyShape{
	int width;
	int height;
	public Rect(int width , int height){
		this.width = width;
		this.height = height;
	}
	public  void getArea(){
		System.out.println("矩形的面积:"+ width*height);
	}
	public  void getLength(){
		System.out.println("矩形的周长:"+ 2*(width+height));
	}
}

class Demo1 {
	public static void main(String[] args) {
		Circle c = new Circle(4.0);
		print(c);
		Rect r = new Rect(3,4);
		print(r);
	}
	public static void print(MyShape s){ // MyShpe s = new Circle(4.0);
		s.getArea();
		s.getLength();
	}
}

(3) 运行结果


9.实例二

(1) 需求:定义一个函数可以返回任意类型的图形对象。

(2) 实例:

//图形类
abstract class MyShape{
	public abstract void getArea();
	public abstract void getLength();	
}

class Circle extends MyShape{
	public static final double PI = 3.14;
	double r;
	public Circle(double r){
		this.r =r ;	
	}
	public  void getArea(){
		System.out.println("圆形的面积:"+ PI*r*r);
	}
	public  void getLength(){
		System.out.println("圆形的周长:"+ 2*PI*r);
	}
}

class Rect  extends MyShape{
	int width;
	int height;
	public Rect(int width , int height){
		this.width = width;
		this.height = height;
	}
	public  void getArea(){
		System.out.println("矩形的面积:"+ width*height);
	}
	public  void getLength(){
		System.out.println("矩形的周长:"+ 2*(width+height));
	}
}

class Demo1 {
	public static void main(String[] args) {
		MyShape m = getShape(0); //调用了使用多态的方法,定义的变量类型要与返回值类型一致。
		m.getArea();	//此时不能写rect,因为只是要返回一个图形,而这个图形不一定是矩形,如果这样写会报错,
		m.getLength();
	}
	public static MyShape  getShape(int i){
		if (i==0){
			return new Circle(4.0);
		}else{
			return new Rect(3,4);
		}
	}
}

(3) 运行结果


10.接口关系下的多态:

(1) 实现关系下的多态:

接口  变量 = new 接口实现类的对象;

(2) 实例:

interface Dao{  
	//接口的方法全部都是非静态的方法。存在同名的非静态方法永远是调用子类的,所以接口中也是调用实现类的方法
	public void add();
	public void delete();
}

//接口的实现类
class UserDao implements Dao{	
	public void add(){
		System.out.println("添加成功!!");
	}
	public void delete(){
		System.out.println("删除成功!!");
	}
}

class Demo1 {
	public static void main(String[] args) {
		//实现关系下的多态
		Dao d = new UserDao(); //接口的引用类型变量指向了接口实现类的对象。
		d.add();
	}
}

(3) 运行结果




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

处女座的码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值