java中面向对象三大特性:封装、继承、多态、抽象、引用类型转换

目录

 

一、封装性:

二、继承性

1.概述

2.为什么要继承?

3.继承的特点

4.继承的限制

5.super用法

​​​​​​案例:

三、多态

1.什么是多态

2.多态的几种形式

直接引用多态

传参多态

返回值多态

四、抽象类

1.概述

2.直接引用多态

3.传参多态

4.返回值多态

五、引用类型转换

1.基本转换

2.强转隐患及处理

六、总结


 

一、封装性:

描述:封装之前学习过方法,方法就是一种封装,在面向对象的封装性中,本质上也是讲方法的封装

封装性:在面向对象中,不要直接调属性,而是通过set/get方法进行封装

好处:结构更清晰,复用性更强,安全性更强

通过封装,将属性设为私有的,外部不能直接修改属性值(从源头上规避直接调用属性),只能通过公开的方法来操作私有的变量,提高了信息的隐蔽性和安全性

用类实现封装,用封装实现高内聚低耦合

封装步骤:

1.编写set/get方法,注意规范写法,set用于赋值,get用于取值

2.属性私有化

二、继承性

1.概述

一个类如果想要具备另外一个类的属性和方法,那么可以通过继承,实现得到父类的资源

Object:所有类的父类

重合点(特征和行为接近)越多,越接近直接父类

重合点越少,越接近Object类

2.为什么要继承?

例:当有两个动物猫、狗,它们都有姓名属性、吃饭、睡觉的方法,如果分开写两个类,每个类都去写这些属性和方法的话,太麻烦,而且代码很冗余,一样的属性和方法写两次。

所以这个时候可以抽象出来他们共有的的东西形成一个父类,如:写一个动物类,这个类有属性和方法,那么我们就可以将猫狗类去继承这个动物类,就可以继承这个动物类的属性和方法,那么这些属性和方法我们只需要在子类中继续调用就行。

好处:减少代码量、减少冗余、提高代码的复用性、提高扩展性

提高扩展性:

当子类继承父类的时候,如果对父类的方法不满意则可以重写父类中的方法。如:动物类有个方法是吃,但是狗类继承了动物类,可以重写这个方法,使方法具有子类的特性

案例:

class Animal{
	String name;
	int    age;
	public void eat() {
		System.out.println(name+"正在吃...");
	}
	public void sleep() {
		System.out.println(name+"正在睡...");
	}
}
class Dog extends Animal{  //Dog继承Animal
	String color;
	public void run() {
		System.out.println(name+"正在跑");
	}
}
class Bird extends Animal{ //Bird继承Animal
	String color;
	public void fly() {
		System.out.println(name+"正在飞");
	}
}
class Fish extends Animal{ //Fish继承Animal
	public void swim() {
		System.out.println(name+"正在游");
	}
}
public class Test1 {
	public static void main(String[] args) {
		Dog dog = new Dog();
		dog.name = "旺财"; //调父类的属性
		dog.color = "黄色"; //调自身独有属性
		dog.run();      //调自身独有方法
		dog.sleep();    //调父类方法
		System.out.println("--------------");
		
		Bird bird = new Bird();
		bird.name = "八哥";
		bird.fly();
		bird.eat();
		System.out.println("--------------");
		
		Fish fish = new Fish();
		fish.name = "小金";
		fish.swim();
		fish.sleep();
		
	}
}

3.继承的特点

在java中只有单继承,没有多继承

但是又多级继承,就是说子类继承的父类还可以又父类(子类可以有爷爷类

父类可以调用父类的父类资源,不能调用子类的资源

子类可以调用父类资源以及它爷爷的资源 

案例:

//案例:爷爷有1000万;爸爸有一辆跑车;儿子有一辆玩具车
class GrandFather{
	String name;
	public void haveMoney() {
		System.out.println(name+"拥有1000万");
	}
}
class Father extends GrandFather{ //多级继承
	public void haveCar() {
		System.out.println(name+"有一辆跑车");
	}
}
class Son extends Father/*,GrandFather*/{//没有多继承
	public void haveToy() {
		System.out.println(name+"有一辆玩具车");
	}
}
public class Test2 {
	public static void main(String[] args) {
		Father father = new Father();
		father.name = "大三"; //调爷爷类的属性
		father.haveMoney();  //调爷爷类的方法
		father.haveCar();    //调自身的方法
		//father.haveToy();  //不能调子类的方法
		System.out.println("===============");
		
		Son son = new Son();
		son.name = "小三";
		son.haveMoney();    //调爷爷类的方法
		son.haveCar();      //调父类的方法
		son.haveToy();      //调自身的方法
	}
}

4.继承的限制

  • 私有的成员不能被继承

  • 构造方法没有继承性

  • 不同包的default权限,没有继承性

构造方法虽然没有继承性,但是当子类继承了父类的时候,实例化子类的时候,优先去调用父类的构造函数,然后才是调用子类的构造函数​------也就是说子类虽然没有继承父类构造函数,但是可以调用父类的构造函数

5.super用法

super表示父类对象;和this有点类似,只是this表示当前对象

在应用上也和this类似;super可以调用属性,方法,构造方法

super VS this

this调属性:调当前对象的属性;如果当前类没有,则根据继承性,调父类属性

this调方法:调当前对象的方法;如果当前类没有,则根据继承性,调父类方法

this调构造方法:调当前类的构造方法

super调属性:调父类的属性

super调方法:调父类的方法

super调构造方法:调父类的构造方法

​​​​​​案例:

//super调属性:
class Person{
	String name="刘亦菲";
}
class Student extends Person{
    String name="凤姐";
	public void show() {
		System.out.println(name);       //凤姐-先调自身,自身没有才调父类属性
		System.out.println(this.name);  //凤姐-先调自身,自身没有才调父类属性
		System.out.println(super.name); //刘亦菲-调父类属性
	}
}
public class Test1 {
	public static void main(String[] args) {
		new Student().show();
	}
}

//super调方法:调的是父类的方法
class Animal{
	public void show() {
		System.out.println("父类的show方法");
	}
}
class Dog extends Animal{
	@Override
	public void show() {
		super.show();  //先调父类的方法
		
		System.out.println("子类的show方法");
	}
}
public class Test2 {
	public static void main(String[] args) {
		new Dog().show();
	}
}

在构造方法中,默认首句会出现super(); 先调用父类无参构造。

为什么这么设计?

原因是,实例化对象的过程是父类资源+子类资源;否则就不会有继承的特点(调父类属性和方法)因为子类继承了父类,所以子类不仅有自身的资源而且还有父类的资源,所以在实例化子类对象的时候,要加载父类的资源,这样就能调用父类的资源,然后再加载自身的资源,这样就实现了继承。

案例:

class A{
	public A() {
		System.out.println("父类A的无参构造");
	}
	public A(int a) {
		System.out.println("父类A的带参构造");
	}
}
class B extends A{
	public B() {
		//super();
		System.out.println("子类B的无参构造");
	}
	public B(int a) {
		//super(a);  //调父类带参   this和super在构造方法中不能共存
		this();      //A无参   B无参   B带参
		System.out.println("子类B的带参构造");
	}
}
public class Test3 {
	public static void main(String[] args) {
		//new B();   //父类A无参; 子类B无参
		new B(66);   //父类A无参; 子类B带参
	}
}

三、多态

1.什么是多态

从字面意思可以知道多态就是多种形态的表现形式。多态的前提其实就是继承或接口,正是因为有了继承、接口,子类继承父类然后去重写父类的方法、实现类实现接口然后重写接口的方法才体现出多态。

 

如:一个动物有吃的方法,而狗继承了动物类,重写吃方法后表现为吃骨头

                                         而猫继承了动物类,重写吃方法后表现为吃猫粮

这就是继承后重写方法所体现出来的多态,多种形态(实现类实现接口同理)

 

 

程序中的多态:将子类对象当成父类看待,这就是多态;换句话说,父类引用指向子类对象,即形成多态

例如:Animal an = new Dog(); //多态核心

多态应用:父类引用指向子类对象,即可调用父类的方法,不能调用子类独有的方法

案例:

class Animal{
	public void eat() {
		System.out.println("动物正在吃...");
	}
}
class Dog extends Animal{
	public void bark() {
		System.out.println("旺财正在汪汪汪...");
	}
}
public class Test1 {
	public static void main(String[] args) {
		Animal animal = new Dog();  //多态核心
		animal.eat();   //父类引用可调用父类方法
		//当成父类看待,则调不了子类方法
		//animal.bark();  //父类引用不能调子类独有方法
	}
}

2.多态的几种形式

直接引用多态

//直接引用多态的方式调用重写方法:
//案例:将猫当成宠物看待,可调用宠物的吃的方法;如果猫有不同吃的行为,则优先调用
class Pet{
	public void eat() {
		System.out.println("宠物正在吃东西...");
	}
}
class Cat extends Pet{
	@Override
	public void eat() {
		System.out.println("猫正在吃...");
	}
}
public class Test2 {
	public static void main(String[] args) {
		Pet pet = new Cat(); //父类引用指向子类对象,优先调子类重写方法
		pet.eat(); //子类有重写方法,优先调子类方法
	}
}

传参多态

//案例:主人喂养宠物,猫,狗都是宠物,都有各自吃的行为
//分析:类-宠物类(父),猫类(子),狗类(子),主人类(第三方类); 方法-吃,喂养
//问题:两个宠物,就需要写两个喂养的方法;后面扩展更多宠物,则继续增加喂养方法
//面向对象设计原则:ocp原则-开闭原则
//o-open:对外部扩展的类持开放状态-例如可扩展很多宠物类(扩展性)
//c-close:对内部修改的代码持关闭状态-例如-主人喂养行为不要增加(维护性,灵活性)

//多态的好处:使程序的扩展性,可维护性更强

class Pet{  //宠物类
	public void eat() { //吃
		System.out.println("宠物正在吃...");
	}
}
class Dog extends Pet{
	@Override
	public void eat() { //重写吃
		System.out.println("旺财正在吃...");
	}
}
class Cat extends Pet{
	@Override
	public void eat() { //重写吃
		System.out.println("加菲猫正在吃...");
	}
}
class Master{  //主人类
	//--------重载方法--------
	/*
	public void feed(Dog dog) {
		dog.eat();  //狗在吃
	}
	public void feed(Cat cat) {
		cat.eat();  //猫在吃
	}*/
	//传参实现的多态
	public void feed(Pet pet) {//Pet pet = new Dog(); 多态
		pet.eat(); //谁传给我,就调谁的 (不要看谁调的,要看谁传的)
	}
}
public class Test1 {
	public static void main(String[] args) {
		Master master = new Master();
		master.feed(new Dog());  //1.主人喂养狗
		master.feed(new Cat());  //2.主人喂养猫
	}
}

返回值多态

 

//返回值多态:调用方法返回子类对象,由父类引用接收;构成返回值多态
//案例:主人购买宠物;根据标识购买不同宠物:1.买鸟 2.买狗
//分析:类-主人类(第三方类);宠物类(父),鸟,狗(子) 方法:购买
class Pet{	
	public void eat() {
		System.out.println("宠物在吃东西");
	}
}
class Bird extends Pet{
	@Override
	public void eat() {
		System.out.println("鸟正在吃东西");
	}
}
class Dog extends Pet{
	@Override
	public void eat() {
		System.out.println("狗正在吃东西");
	}
}
class Master{
	public Pet bug(int type) {
		if(type==1) {
			return new Bird();
		}else if(type==2) {
			return new Dog();
		}else {
			return null;
		}
	}
}
public class Test1 {
	public static void main(String[] args) {
		Master master = new Master();
		Pet pet = master.bug(1); //返回子类对象;用父类Pet接收,形成多态
		pet.eat(); //调子类重写方法
	}
}

四、抽象类

1.概述

某些类具有某种方法,但不能具体实现,这样的方法叫抽象方法;所在的类就是抽象类。

例如:动物类(抽象类)----叫(抽象方法)

这样的抽象类我们无法具体化(不能实例化对象),可以交给子类具体化以及具体实现。

好处:

更自然地使用多态; 抽象方法可以当成模板来使用

抽象方法一定在抽象类,抽象类中不一定都是抽象方法
抽象类细节说明:
1.抽象类能否具体化                不能被实例化
2.抽象类能否有构造方法         因为子类构造方法可以调:super(),可以有
3.有抽象方法的类一定是抽象类吗?     是的
4.抽象类是否必须有抽象方法?        可以没有抽象方法
5.抽象类是否可以有非抽象方法?     可以有
6.父类为抽象类,子类是否必须要重写抽象方法?  不是必须的,也可以将子类变为抽象类

 

2.直接引用多态

案例:

abstract class Animal{ //抽象类
	public abstract void bark();  //抽象方法--模板
	
	public Animal() {}  //可以有构造方法
	
	public void eat() {  //非抽象方法
		
	}
}
//The type Dog must implement the inherited abstract method Animal.bark()
//报错处理方案:1.重写父类方法   2.把自身变抽象
/*abstract*/ class Dog extends Animal{
	@Override
	public void bark() {
		System.out.println("大黄正在汪汪汪的叫...");
	}
	
	public void run() {
		System.out.println("大黄正在跑....");
	}
}
public class Test1 {
	public static void main(String[] args) {
		//Animal animal = new Animal();  //抽象类是不能具体化的
		Animal animal = new Dog();   //抽象类就是为多态而生  抽象类直接引用多态
		animal.bark();      //抽象类指向子类对象,可调用子类重写方法
		//animal.run();     //不可以调子类独有的方法
		//结论:后续使用继承的多态,基本都是抽象类实现多态;因为应用更明确,且父类方法不会太浪费
	}
}

3.传参多态

案例:

//案例:主人喂养宠物,猫,猪都是宠物,都有各自吃的行为
//分析-宠物类(父),猫类(子),猪类(子),主人类(第三方类); 方法-吃,喂养:
abstract class Pet{ //抽象类
	public abstract void eat();  //抽象方法
}
class Cat extends Pet{
	@Override
	public void eat() {
		System.out.println("加菲猫正在吃...");
	}
}
class Pig extends Pet{
	@Override
	public void eat() {
		System.out.println("佩奇正在吃...");
	}
}
class Master{
	public void feed(Pet pet) { //传参多态
		pet.eat();
	}
}
public class Test2 {
	public static void main(String[] args) {
		Master master = new Master();
		master.feed(new Cat()); //主人喂猫
		master.feed(new Pig()); //主人喂猪
	}
}

4.返回值多态

案例:

//返回值多态:调用方法返回子类对象,由父类引用接收;构成返回值多态
//案例:小孩购买玩具;根据标识购买不同玩具:1.买鸟 2.买鱼
//分析:类-小孩类(第三方类);玩具类(父),鸟,鱼(子) 方法:购买
abstract class Toy{
	public abstract void start();
}
class Bird extends Toy{
	@Override
	public void start() {
		System.out.println("玩具鸟正在发射..");
	}
	
}
class Fish extends Toy{
	@Override
	public void start() {
		System.out.println("玩具鱼正在发射..");
	}
}
class Boy{
	public Toy buy(int type) {
		if(type==1) {
			return new Bird();
		}else if(type==3) {
			return new Fish();
		}else {
			return null;
		}
	}
}
public class Test3 {
	public static void main(String[] args) {
		Boy boy = new Boy();
		Toy toy = boy.buy(1);
		toy.start();
	}
}

五、引用类型转换

在基本类型中有类型转换:转的前提是类型要兼容;然后低类型可转高类型,高类型也能转低类型(强转)

在引用类型中,一样有类型转换:转换的前提是必须建立关系:父子关系(后面的接口也可转)

在引用类型的转换中,有向上转和向下转两种

1.基本转换

向上转---子类转父类,默认转(多态核心)

向下转---父类转子类,强转

案例:

//父类Animal与子类Dog之间的相互转换:
class Animal{
}
class Dog extends Animal{
}
public class Test1 {
	public static void main(String[] args) {
		Animal animal = new Dog();  //向上转-默认转(多态核心)
		
		Dog dog = (Dog)animal;    //向下转-强转
	}
}

2.强转隐患及处理

强转的隐患:类型转换异常

可以使用instanceof处理类型转换的异常  instanceof-做判断的关键字

instanceof不是真实处理问题,而是规避异常

案例:

//父类与子类之间的转换:
class Pet{ //父类
	
}
class Bird extends Pet{ //子类
	
}
class Pig extends Pet{  //子类
	
}
public class Test2 {
	public static void main(String[] args) {
		Pet pet = new Bird();
		//类型转换异常:Bird cannot be cast to Pig  鸟不能转成猪
		//Pig pig = (Pig) pet;  //向下转-强转(出现隐患)
		
		//可以使用instanceof处理类型转换的异常  instanceof-做判断的关键字
		// if (args instanceof type) {   args: 变量   type:类型
		
		if (pet instanceof Pig) {
			Pig pig = (Pig) pet;
			System.out.println("pet的本质类型是Pig");
		}else if(pet instanceof Bird) {
			Bird bird = (Bird)pet;
			System.out.println("pet的本质类型是Bird");
		} 
		//结论:instanceof不是真实处理问题,而是规避异常
	}
}

六、总结

1.多态
继承是前提
多态核心-父类引用指向子类对象;(重点)
应用:可调用父类方法,不能调子类独有方法
2.多态中的重写(重点)
直接引用多态;
传参多态--多态优势(需要第三方类); 返回值多态(需要第三方类)
3.引用类型转换
基本转:向上转(默认转),向下转(强转)
强转隐患处理--instanceof
4.抽象类(重点)
和父类多态类似;只是抽象类更常用于多态中
理解抽象类细节,好处
应用:直接引用,传参多态,返回值多态

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值