一、封装
前言:我们知道面对对象的编程包含了封装、继承和多态3个方面。而个人的观点来看,我觉得封装是和类的编程方式最贴切的一种技术,类就是将需要实现的功能抽象出若干个独立的模块来进行开发,每个模块都有与其绑定的一些属性和方法,通过在程序中新建该类的对象来对这个模块中的功能进行调用和维护。
1、首先我们就先介绍一下类的成员中的public、protected、private三种继承修饰符:public修饰的成员是几乎没有什么限制的,既可以直接被本包中的父类对象或者是该父类的子类对象调用,甚至还可以被该类所在的包(package)以外的包内通过父类对象或者是该父类的子类对象调用;private仅仅能够被这个类内部的成员调用;如果你没有使用任何的继承修饰符,那么你就默认使用了default的修饰符。
package demo;
//父类
public class Person {
public String str_pb = "public!"; //public成员
private String str_Pri = "private"; //private成员
//protect成员
protected void sayProtected() {
System.out.println("this is protect function!");
}
//默认成员
void sayDefault() {
System.out.println("this is Default function!");
}
}
package demo;
//与父类在一个包的子类
public class Teacher extends Person{
}
这里是父类以及和父类在一个包里的子类
package demo;
public class main {
public static void main(String[] args) {
Person p = new Person(); //创建父类对象来调用相关成员
p.sayProtected(); //成功调用protected成员
p.str_pb = "public"; //成功调用public成员
p.sayDefault(); //成功调用default成员
p.str_Pri = "private"; //error! 不能通过对象(类外)来调用private成员
Teacher te = new Teacher(); //创建Person的子类Teacher的对象来调用相关成员
te.str_pb = "public"; //成功调用public成员
te.sayDefault(); //成功调用default成员
te.sayProtected(); //成功调用protected成员
te.strPri = "private"; //error! 子类不能继承私有成员
}
}
//另一个包中继承了Person的子类
package demo_Other;
import demo.Person;
public class Student extends Person{
}
//这也是另一个包在调用demo中的Person类
package demo_Other;
import demo.Person;
public class test {
public static void main(String[] args) {
Person p = new Person(); //创建一个demo包中的Person对象(父类)
p.sayProtected(); //error! 不能调用protected成员
p.str_pb = "public"; //成功调用public成员
p.sayDefault(); //error! 不能调用default成员
p.str_Pri = "private"; //error!不能调用private成员
Student st = new Student(); //创建一个demo_Other包中的Student对象(子类)
st.sayProtected(); //error! 不能调用protected成员
st.str_pb = "public"; //成功调用public成员
st.sayDefault(); //error! 不能调用default成员
st.str_Pri = "private"; //error!不能调用private成员
}
}
总结:Public不论调用的对象是否和该类的代码在一个包,都可以调用public的成员,且public成员会可以在一个包内被继承,也可以跨包继承并被调用;Protected和Default本质上是一样的,都可以被同包内继承和调用,但是跨包无法继承也不能被调用;Private不能被继承和类外的对象调用。
2、那么所谓的封装现在解释起来就十分的清楚了,就是将一些重要的数据成员的继承修饰符设置为private,这样类外就不能对这个成员的数据进行任何的查找或者修改的操作,然后在类内设置get和set方法来分别对这个私有数据成员进行查询和修改的操作。
public class Person {
private String address = "China!";
private String gender = "male";
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
二、继承
1、继承的概念我认为是为了降低代码的重复度从而提高代码的重复利用率和整洁率,首先确定一个最大的抽象类,这个类里面有之后你要细分的所有类的一些公共特点。举个例子,假设抽象类叫Animal,是一个生命体,具有吃和跑2个基本动作。我们的子类分别是Dog和Cat,这两个子类都有Animal这个父类的2种基本动作,那么只要2个子类直接继承父类就可,不用洋洋洒洒将这些功能再重复写若干遍(父类的构造方法是不能被子类继承的)。
2、总体来讲继承分为显式继承和隐式继承2种,当你创建一个类的时候会默认继承java.lang.Object的类来实现类的基本功能,这就是隐式继承。显式继承就是你在一个类的后面加上extends关键字,具体代码见上面。
3、继承的方法重写:在继承了父类之后,父类的基础方法可能并不能准确的满足子类的需求。子类就可以对父类的方法进行重写,来实现自己的独特需求。
//父类
public class Animal {
protected void run() {
System.out.println("这个动物会跑");
}
protected void eat() {
System.out.println("这个动物会吃东西");
}
}
//子类
public class Dog extends Animal{
//方法重写
protected void run() {
System.out.println("狗会跑");
}
}
//运行
public class main {
public static void main(String[] args) {
Dog d = new Dog();
d.run(); //这里会直接输出“狗会跑”而不是父类的“动物会跑”
}
}
这里是直接对父类的run()方法进行了重写,当然如果想要再次调用父类的run方法也是可以的,只要使用super关键字就行,super关键字其实就是默认的父类对象,而且在子类的方法名和父类方法名重名的时候还可以进行区分。
public class Dog extends Animal{
//方法重写
protected void run() {
System.out.println("狗会跑");
super.run();
}
}
public static void main(String[] args) {
Dog d = new Dog(); //这里运行会出现“狗会跑”和“动物会跑”证明父类的方法和子类的方法都被成功
d.run(); //调用
}
4、向上转型和向下转型:向上转型就是将子类的实例赋值给父类的对象;向下转型指的是将父类的对象强制转换为子类的对象。
public static void main(String[] args) {
Animal animal;//新建一个animal的对象(未实例化)
animal = new Dog(); //向上转型,将子类的实例赋值给父类
Cat c = (Cat) animal; //error! 这里dog是无法转换成cat的
Dog d = (Dog) animal; //向下转型,将一个父类对象强制转换为子类对象
d.run();
}
小结:转型可以将预备好的抽象类的对象在需要的时候转换为具体的类的对象