Java回顾——封装、继承和多态

我们都知道面向对象的三大基本特征是:封装、继承和多态。今天简要说这三个特征。

封装

封装是什么:

封装将类的外部接口与类的具体实现区分开,隐藏实现细节,用户只能使用外部接口,当实现细节改变时,外部接口保持不变,确保调用它的代码还继续工作。

public class User{
	//定义为private的成员变量,外界无法直接访问
	private String name;
	/**
	 *提供set方法,来改变私有成员name的值
	 */
	public void setName(String name){
		this.name = name;
	}
	/**
	 *提供get方法,让外界获取私有成员name的值
	 */
	public String getName(){
		return this.name;
	}
}

这是一个封装的简单例子,外界用户无法直接访问用户名字这个属性,而需要调用get或set方法来对类中属性进行操作。换到现实中,我们见到一个人,没办法直接知道他的名字,交换名片,就相当于调用了getName方法,便获取了他的名字。

再举个现实的例子,比如说遥控器,我们看电视要用,但是有一个按键坏掉了,我们把那个按键修好,你还可以继续用。这些按键就是提供给用户的外部接口,遥控器里面的内部实现,为什么按这个就能实现这个功能用户不需要知道,就隐藏起来了,这就是封装。

为什么要封装:

1、隐藏类的实现细节:回到遥控器的例子,用户不需要知道为什么可以换台,只需要知道怎么换台就可以了。
2、让使用者只能通过事先定制好的方法来访问数据:还是遥控器,你按1,不能出来3,什么按键(方法)是做什么的,安排的明明白白,所以为什么隐藏实现细节。
3、方便加入逻辑控制,限制对属性的不合理操作:看到那个代码例子,上面直接是传入一个字符串就把名字改了,因为只是举个例子,但我们实际改名字的时候不可能这么简单,里面加一些控制,比如说你要和你爸姓,等等,让不合理的操作不被执行。
4、便于修改,增强代码可维护性:继续说改名字,我们修改了改名字的方法,而你改名字的时候依然是调用这个方法,维护代码并不影响用户使用。

封装怎么做:

通过访问控制修饰符:

修饰符/访问权限 同类 同一包中的类 子类 不同包中的类
public
protected ×
friendly × ×
private × × ×

(√表示可以被访问,×表示不能被访问)
(默认权限为friendly)
其实第一篇Hello World就有说,现在知道是通过这四个修饰符来实现封装了。

继承

write once,only once,写一次,仅写一次。
上面这句话,是告诉我们为什么要有继承,为了提高程序的复用性。
比如说,我们写了一个类,实现了几个功能,到了后期呢,我们发现这些功能不够,要添加功能,但一般不会在已有代码中加新代码,我们会新建一个类,继承之前的类,然后在新的类中写新功能,之前定义的功能我们也不用重新写,这就是累积开发,也是开发过程中我们应该遵守的原则,叫开闭原则
为什么呢?我们之前写好的类是经过测试可以正常运行的,我们便不去修改,在新类中增加新功能,如果出错,直接在新类中查找,将新错误隔离在了新代码里。开闭原则,简而言之一句话:对扩展开放,对修改关闭,为什么这样做,上面也解释了,这样提高了系统的可维护性

关于继承还有一些要注意的:

  • 子类只能继承父类中的所有可见成员(有些是不可继承的,比如被private修饰的,子父类不同包时被默认权限修饰的,参见上面访问控制修饰符)。
  • 父类的构造方法是不可以被继承的。
  • 每个类都只能直接继承于一个父类(只能由一个爸爸)
  • 所有类都直接或间接继承与java.lang.Object(上帝类)
  • 方法重写/覆盖(Override),后面单独拿出来讲

多态

概念:在同一继承树上的不同对象针对同一行为的不同表现
理解:动物会叫,猫是动物,狗是动物,猫叫是喵,狗叫是汪
常见运用:父类引用指向子类对象。

//动物类
class Animal{
	public void eat(){
		System.out.println("动物吃东西");
	}
}
//猫类继承动物类
class Cat extends Animal{
	public void eat(){
		System.out.println("猫吃鱼");
	}
}
//狗类继承动物类
class Dog extends Animal{
	public void eat(){
		System.out.println("狗吃骨头");
	}
}
class Test{
	public static void main(String arg[]){
		//父类引用  变量名 = 子类对象
		Animal cat = new Cat();
		Animal dog = new Dog();
		//执行子类方法
		cat.eat();//猫吃鱼
		dog.eat();//狗吃骨头
	}
}

上面这个例子就是多态的一个简单体现,父类引用指向子类对象,运行时执行子类方法
注意:方法必须调用的是父类中存在的方法。
多态,在同一继承树上的不同对象针对同一行为的不同表现: 不同对象指的是不同的子类,同一行为指的是他们共有的方法,类是对具有共同属性和行为的事物的抽象,而行为在不同对象的表现是不同的。

类型转换

//向上转型(引用由子类转为父类)自动转换(隐式转换)
//复习new关键字:1开辟空间,2调用构造方法创建对象,3返回引用
Animal dog = new Dog();
//向下转型(引用由父类转为子类)须强制类型转换
Dog myDog = (Dog)dog;

向下转型时容易出错,可以加判断:

//父类引用
Animal cat = new cat();
//判断cat指向的对象是否属于Dog类
if(cat instanceof Dog){
	//如果是则将父类引用转为子类引用,不过很明显不是,代码块不会执行
	Dog dog = (Dog)cat;
}
Dog dog = (Dog)cat;//如果不判断,则会直接报错:ClassCastException,类型转换异常

判断的关键字是:instanceof

就说这么多,欢迎大家批评指正。

猜你喜欢

转载自blog.csdn.net/weixin_43622082/article/details/86665164