面向对象三大特征_封装、继承、多态

面向对象三大特征

封装

继承

多态

封装

概述

是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。核心是归纳总结

好处

提高代码的复用度、安全性,不必关心具体细节,便于开发

JavaBean 规范化封装

1. 要求Java中的所有实体类成员变量全部私有化,最少提供一个无参数构造方法,对应成员变量实现setter和getter方法
2. JavaBean规范,是为了后期开发汇总更好的代码适配度,提高代码运行的统一性,能够满足框架的使用
3. JavaBean规范只是一个规范,而且是作为一个基础规范,操作都是可以使用快捷键来完成的!!!
class Person {
	private String name;
	private int age;
	private char sex;
	private boolean alive;
	
	public Person() {}
	
	public String getName() {
		return this.name;
	}
	
	public int getAge() {
		return this.age;
	}
	
	public char getSex() {
		return this.sex;
	}
	
	public boolean isAlive() {
		return alive;
	}
	
	public void setAlive(boolean alive) {
		this.alive = alive;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public void setAge(int age) {
		this.age = age;
	}
	
	public void setSex(char sex) {
		this.sex = sex;
	}
}

类与类之间的调用(多类合作)

汽车类

public class Car {
	private String color;
	private float speed;
	private int tyreTotal;
	// 将自定义的引擎类作为汽车类的成员变量
	private Engine engine;

	public Car() {
		super();
	}

	public Car(String color, float speed, int tyreTotal, Engine engine) {
		super();
		this.color = color;
		this.speed = speed;
		this.tyreTotal = tyreTotal;
		this.engine = engine;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public float getSpeed() {
		return speed;
	}

	public void setSpeed(float speed) {
		this.speed = speed;
	}

	public int getTyreTotal() {
		return tyreTotal;
	}

	public void setTyreTotal(int tyreTotal) {
		this.tyreTotal = tyreTotal;
	}
	
	public Engine getEngine() {
		return engine;
	}

	public void setEngine(Engine engine) {
		this.engine = engine;
	}

	/**
	 * 飙车方法,如果轮胎个数不为4,需要找修理厂
	 */
	public void race() {
		if (4 == tyreTotal) {
			System.out.println("开着" + this.color + "颜色的保时捷以" + speed +  "迈的速度飙车");
		} else {
			System.out.println("轮胎出问题了,要找修理厂");
		}
	}
}

修理厂类

public class Factory {
	private String name;
	private String tel;
	private String address;
	
	public Factory() {
		super();
	}
	
	public Factory(String name, String tel, String address) {
		super();
		this.name = name;
		this.tel = tel;
		this.address = address;
	}

	public String getName() {
		return name;
	}

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

	public String getTel() {
		return tel;
	}

	public void setTel(String tel) {
		this.tel = tel;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}
	
	/**
	 * 修车方法,需要传入一辆汽车
	 * 
	 * @param car 传入需要修理的车对象
	 * @return 返回修好的车
	 */
	public Car fix(Car car) {
		
		System.out.println("欢迎来到" + this.name + "修车厂,我们的电话是:" + this.getTel() + ",我们的地址是:" + this.address);
		
		if (car.getTyreTotal() != 4) {
			car.setTyreTotal(4);	// 将轮胎改成4个
			car.setSpeed(80.0F);	// 速度降到80迈
			System.out.println("修车ing~~~");
		}

		// 拿到汽车的引擎
		Engine engine = car.getEngine();
		
		// 拿到引擎的名字和排量
		String engineName = engine.getName();
		float engineDisplacement = engine.getDisplacement();
		
		if (null != engineName) {
			System.out.println("检查引擎没有问题,排量是:" + engineDisplacement + "T");
		} 
		
		System.out.println("修理完毕");
		
		return car;
	}
}

引擎类

public class Engine {
	// 型号
	private String name;
	// 排量
	private float displacement;

	public Engine() {
		super();
	}

	public Engine(String name, float displacement) {
		super();
		this.name = name;
		this.displacement = displacement;
	}

	public String getName() {
		return name;
	}

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

	public float getDisplacement() {
		return displacement;
	}

	public void setDisplacement(float displacement) {
		this.displacement = displacement;
	}
}

测试类

public class TestCar {
	public static void main(String[] args) {
		
		// 这里有一个引擎
		Engine engine = new Engine();
		engine.setName("XX");
		engine.setDisplacement(1.0F);		
		
		// 买了一辆保时捷
		Car car = new Car("红色", 300.0F, 4, engine);

		// 飙车
		for (int i = 1; i <= 10; i++) {
			car.setSpeed(car.getSpeed() + 2);
			car.race();
		}

		// 如果车的速度太快,达到了320迈,就会爆胎
		if (car.getSpeed() >= 320.0) {
			// 有一个车轱辘爆胎了
			car.setTyreTotal(3);
		}

		// 继续飙车
		car.race();

		// 找修理厂
		Factory factory = new Factory("摇滚王子修车厂", "15844517927", "吉安");

		// 修车,拿到修好的车
		Car fixedCar = factory.fix(car);

		// 飙车
		for (int i = 1; i <= 10; i++) {
			fixedCar.setSpeed(fixedCar.getSpeed() + 2);
			fixedCar.race();
		}
		
		// 随便找个修车厂修车,此时我只关心修车,不在乎其他的内容
		// new Factory().fix(car);
	}
}

匿名对象

概述

没有名字的对象,是对象的一种简化表示形式

特性

一次性,每次使用都是一个新的对象

使用情景

1、对象调用方法仅使用一次,然后等待销毁

2、作为实际参数传递

public class TestDog{
	public static void main(String[] args) {
        // 对象调用方法仅使用一次
		new Dog().sleep();
		
        // 作为实际参数传递
		useDog(new Dog());
	}
	
	public static void useDog(Dog dog) {
		dog.sleep();
	}
}

class Dog {
	String name;
	int age;
	
	public void sleep() {
		System.out.println("小狗睡觉.....");
	}
}

优点

提高开发效率,简化代码结构

继承

概念

把多个类中相同的成员给提取出来定义到一个独立的类中。然后让这多个类和该独立的类产生一个关系,这多个类就具备了这些内容。这个关系叫继承。

关键字:extends

格式:
	class Son extends Father {
    
	}

一个孩子只能有一个父亲
一个父亲可以有多个孩子

特点

1、Java为单继承,一个类只能有一个直接父类,但可以多级继承,属性和方法逐级叠加
2、构造方法只可服务于本类,不可继承,子类执行构造方法前会默认调用父类的无参构造方法。可以通过super()去访问父类的构造方法
3、private 修饰的属性和方法不能被继承

extends

public class Demo {
	public static void main(String[] args) {
		// 创建一个父类对象
		Father father = new Father();
		
		// 父类调用父类的属性和方法
		father.name = "父";
		System.out.println(father.name);
		father.game();
		
		System.out.println("-------------");
		
		// 创建一歌子类对象
		Son son = new Son();
		
		// 子类调用子类的属性和方法
		son.age = 16;
		System.out.println(son.age);
		son.study();
		
		// 子类调用父类的属性和方法(public修饰)
		son.name = "子";
		System.out.println(son.name);
		son.game();
		
		
		/*
		 * 子类调用父类private修饰的属性和方法
		 * 
		 * 报错
		 * The field Father.suffer is not visible
		 * The method cook() from the type Father is not visible
		 * 
		 * 由此可知子类不能调用父类私有化的属性和方法
		 */
//		son.suffer = 10;
//		son.cook();
	}
}

public class Father {
	public String name;
	
	private int suffer;
	
	public void game() {
		System.out.println("下棋");
	}
	
	private void cook() {
		System.out.println("做饭");
	}
}

public class Son extends Father{
	public int age;
	
	public void study() {
		System.out.println("子类 -- 学习");
	}
}

子类构造方法执行前默认先执行父类的无参构造方法

class Father {
	String name;

	public Father() {
		System.out.println("Father's Constrator be performed");
	}
}

class Son extends Father {
	int age;

	public Son() {
		System.out.println("Son's Constrator be performed");
	}
}

public class TestSon {
	public static void main(String[] args) {
		Son son = new Son();
	}
}

结果

Father's Constrator be performed
Son's Constrator be performed

【注意】Son 的构造方法中编译器默认生成 super(); 用来调用父类的构造方法,目的是为了初始化父类字段,因为子类可能会用到

继承内存分析图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QCqczLWa-1659320475378)(Pictures\继承内存分析图.jpg)]

优点

1、提高了代码的复用性
2、提高了代码的维护性
3、让类与类之间产生了一个关系,是多态的前提

缺点

1、让类的耦合性增强。这样某个类的改变,就会影响到其他和该类相关的类
2、打破了封装性

总结

Java中只有单继承

子类可以继承父类的非私有属性和方法(非private修饰的)

执行子类的构造方法前会默认执行父类的无参构造方法

方法重写【Override】

引言

开发中父类的方法不一定适用于子类,因为父类方法不能更改,在子类中新增方法会造成代码的冗余,而且不符合逻辑

要求

1、应用于继承和实现接口
2、返回值类型,方法名,形参列表与父类一致
3、使用@Override注解来标识
4、重写方法的访问修饰符权限不能低于父类
	private < 默认(什么都不写) < protected < public
public class Son extends Father{
	public int age;
	
	@Override
	public void game() {
		System.out.println("玩红色警戒");
	}
	
	public void study() {
		System.out.println("子类 -- 学习");
	}
}

public class Father {
	public String name;
	
	private int suffer;
	
	public void game() {
		System.out.println("下棋");
	}
	
	private void cook() {
		System.out.println("做饭");
	}
}

public class Demo1 {
	public static void main(String[] args) {
		Son son = new Son();
		son.game();
	}
}

优点

既沿袭了父类的方法名,又实现了子类的扩展

总结

1、方法的重写能够在不新增方法的情况下实现子类的扩展

2、方法重写要求方法声明格式和父类完全一致(访问修饰符不能小于父类)

3、@Overrid关键字用来开启格式检测,如果不一致就会报错

多态

二者具有直接或间接的继承关系时,父类引用指向子类对象,从而产生多种形态;接口的引用指向实现接口的类对象也是多态

特点

多态场景下,父类引用调用方法,如果被子类重写过,优先执行子类重写过后的方法

public class TestCar {
	public static void main(String[] args) {
        // 父类引用指向子类对象
		Vehicle vehicle = new Car();
        
        // 优先执行子类重写过的方法
		vehicle.run();	// Car run!!!
	}
}

class Vehicle {
	public void run() {
		System.out.println("Vehicle run!!!");
	}
}

class Car extends Vehicle {
	@Override
	public void run() {
		System.out.println("Car run!!!");
	}
}

应用场景一

使用父类作为方法形参实现多态,使方法参数的类型更为宽泛

public class TestCar {
	public static void main(String[] args) {        
        Vehicle vehicle = new Car();
        vehicle.type = "小汽车";
        
		Bike bike = new Bike();
		bike.type = "自行车";
		
		Bus bus = new Bus();
		bus.type = "公交车";
		
		Employee employee = new Employee("你的迪丽热巴");
		employee.goHome(vehicle);
		employee.goHome(bus);
	}
}

class Employee {
	String name;

	public Employee() {
	}
	
	public Employee(String name) {
		this.name = name;
	}

	public void goHome(Vehicle vehicle) {
		System.out.println(this.name + "乘坐" + vehicle.type + "交通工具回家");
	}
}

class Vehicle {
	String type;

	public void run() {
		System.out.println("Vehicle run!!!");
	}
}

class Bus extends Vehicle {
	@Override
	public void run() {
		System.out.println("Bus run!!!");
	}
}

class Car extends Vehicle {
	@Override
	public void run() {
		System.out.println("Car run!!!");
	}
}

class Bike extends Vehicle {
	@Override
	public void run() {
		System.out.println("Bike run!!!");
	}
}

结果

你的迪丽热巴乘坐小汽车回家
Car run!!!
你的迪丽热巴乘坐公交车回家
Bus run!!!

应用场景二

使用父类作为方法返回值实现多态,使方法可以返回不同子类对象

public Vehicle buyVehicle(int money) {
		Vehicle vehicle = null;

		if (money >= 100) {
			Bus bus = new Bus();
			bus.speed = 60;
			bus.price = 1230000.0;
			bus.seatNum = 16;
			bus.type = "公交车";
			vehicle = bus;

		} else if (money >= 30) {
			Car car = new Car();
			car.price = 310000.0;
			car.speed = 90;
			car.type = "小汽车";
			car.brand = "BMW";
			vehicle = car;

		} else if (money >= 1) {
			Bike bike = new Bike();
			bike.type = "捷安特自行车";
			bike.speed = 40;
			bike.price = 2000.0;
			bike.color = "红色";
			vehicle = bike;
		}

		return vehicle;
	}

向上装箱与向下拆箱

class Animal{}

class Cat extends Animal{}

class Dog extends Animal{}

class Fish extends Animal {}

public class Test {
	public static void main(String[] args) {
		showAnimal(new Animal());	// code.polymorphic.animal.Animal@7852e922
		// 向上转型
		showAnimal(new Cat());	// code.polymorphic.animal.Cat@4e25154f
		// 向上转型
		showAnimal(new Dog());	// code.polymorphic.animal.Dog@70dea4e
		// 向上转型
		showAnimal(new Fish());	// code.polymorphic.animal.Fish@5c647e05
		
		System.out.println("----------------------");
		
		Animal animal = getAnimal();
		// 向下转型
		Cat cat = (Cat) getCat();
		// 向下转型
		Dog dog = (Dog) getDog();
		// 向下转型
		Fish fish = (Fish) getFish();
		
		System.out.println(animal);	// code.polymorphic.animal.Animal@33909752
		System.out.println(cat);	// code.polymorphic.animal.Cat@55f96302
		System.out.println(dog);	// code.polymorphic.animal.Dog@3d4eac69
		System.out.println(fish);	// code.polymorphic.animal.Fish@42a57993
	}
	
	/**
	 * 展示动物
	 * @param animal
	 */
	public static void showAnimal(Animal animal) {
		System.out.println(animal);
	}
	
	/**
	 * 得到动物
	 * @return 返回一个Animal对象
	 */
	public static Animal getAnimal() {
		return new Animal();
	}
	
	/**
	 * 得到猫
	 * @return 返回一个Cat对象
	 */
	public static Animal getCat() {
		return new Cat();
	}
	
	/**
	 * 得到狗
	 * @return 返回一个Dog对象
	 */
	public static Animal getDog() {
		return new Dog();
	}
	
	/**
	 * 得到鱼
	 * @return 返回一个Fish对象
	 */
	public static Animal getFish() {
		return new Fish();
	}
}

instanceof 关键字

用于判断当前对象是否是某个类,或者其子类、实现类的实例。如果是返回true,否则返回false。

/**
 * 动物类
 */
class Animal {
}

/**
 * 老虎类
 */
class Tiger extends Animal {
	
}

/**
 * 熊猫类
 */
class Panda extends Animal {
	
}

/**
 * 猴子类
 */
class Monkey extends Animal {
	
}

public class AnimalDemo {
	public static void main(String[] args) {
		Animal ani = getAnimal();
		
		if (ani instanceof Panda) {
			// ani一定是panda对象或子类对象
			Panda panda2 = (Panda) ani;
			System.out.println("这是熊猫:" + panda2);
			showPanda(panda2);
		} else {
			System.out.println("这是动物:" + ani);
		}
	}
    
    // 获取动物,返回一个Panda对象
	public static Animal getAnimal() {
		return new Panda();
	}
    
    // 展示熊猫对象
    public static void showPanda(Panda panda) {
		System.out.println(panda);
	}
}

【注意】使用 instanceof 关键字做判断时, instanceof 操作符的左操作数必须和右操作类或者接口存在继承或实现关系

总结

1、父类引用指向子类对象,接口引用指向实现类对象

2、instanceof用以比较对象是否是类或父类的实例,接口的实现类


版权声明:本文为Angeliaz原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。