4.面向对象的特征:封装、继承、多态
4.1封装(Encapsulation):
4.1.1什么是封装?
封装是指隐藏对象的属性及内部实现细节,仅对外提供公共访问的方式.
4.1.2 封装的好处:提高安全性、提高复用性、将变化隔离、便于使用。
4.1.3封装的原则:
1,不需要对外提供的内容都隐藏起来。
2,对象的属性都隐藏起来,仅对外提供公共访问方法。
如:
class Person{
private int age;
private String name;//将属性都隐藏起来,private私有化是封装的一种方式。
//对外提供公共访问方法,setXXX,getXXX
public void setAge(int age){
this.age=age;
}
public int getAge(){
return this.age;
}
public void setName(String name){
this.name=name;
}
public String getName(){
return this.name;
}
}
4.2继承(Inherit):
4.2.1什么是继承?
对多个类进行共性类容的向上抽取,就形成了父类;被抽去的类,就是子类,这就是一个继承的体系。
继承的关系是is a关系,当A类描述事物是B类的一种,A就可以继承B,使用关键字extends。
4.2.2继承的好处:
1,提高代码的复用性。(子类中相同的内容,抽取到了父类)
2,让类与类之间产生关系。
3,继承是多态的前提。
注意:java中的一般类之间只能单继承,不支持多继承,因为多继承会产生调用的不确定性,但是支持多层继承,如:……D extends C extedns B extends A…..。接口和接口之间可以多继承,这是因为接口中的方法都是抽象方法,没有方法体。Java对多继承进行了改良,支持多实现。
如: class Fu{ void show(){ System.out.println(“Fu show”); } } class Zi extends Fu{ void method(){ System.out.println(“Zi show”); } } /* Zi类继承Fu类,Zi类就具有了和Fu类相同的内容。 */
4.2.3 super关键字
在继承体系中,子类继承父类,子类具有了父类中的内容,这是因为子类持有父类的引用,就是super。this代表本类对象的引用,而super则代表父类对象的引用。子类通过super可以直接调用父类中的成员,不包括私有的。
1,当子类成员变量和父类成员变量重名时,可以用super来区分。
2,super关键字可以用来在子类构造函数中调用父类中的构造函数。
如:
public class Demo {
public static void main(String[] args) {
new Student(23,"张三").method();
}
}
class Person{
int age;
String name;
Person(){}
Person(int age,String name){
this.age=age;
this.name=name;
}
void show(){
System.out.println("");
}
}
class Student extends Person{
Student(int age,String name){
super(age,name);//这里调用的是有参的构造函数,super()可以调用父类中无参数的构造函数.
}
void method(){
System.out.println(this.age+":"+this.name);
}
}
4.2.4 继承时子类成员的特点
1,成员变量在继承体系中,子类和父类的成员变量重名时用super来区分。
如:
public class Demo {
public static void main(String[] args) {
new Student().method();
}
}
class Person{
int age=23;
String name="张三";
void show(){
System.out.println("");
}
}
class Student extends Person{
int age=22;
String name="李四";
void method(){
System.out.println(this.age+":"+this.name);//this调用本类中的成员。
System.out.println(super.age+":"+super.name);//super调用父类中的成员。
}
}
注意:父类中private修饰的成员子类是无法继承的.private修饰的成员只在本类中有效.
2,成员函数
当子类中的成员函数和父类中的成员函数一模一样时,用子类的对象调用该函数时,会调用子类的函数,覆盖父类中的成员函数,这就是函数的覆写.
如:
class Person{
int age;
String name;
void show(){//父类中的成员函数show()
System.out.println("Person show");
}
}
class Studentextends Person{
void show(){//子类中的成员函数show()
System.out.println("Student show");
}
}
publicclass Demo {
publicstaticvoid main(String[] args) {
Student s=new Student();
s.show();//子类对象在调用和父类中一模一样的成员函数时,会覆写父类中的成员函数
}
}
/*
结果:
Student show
*/
函数覆写的前提:
1,类与类,类与接口要有继承的关系或实现的关系;
2,子类中的函数权限要大于或等于父类中被覆写的函数的权限,但被覆写的函数不能是private权限,因为private修饰的成员不能被继承.
3,函数的声明必须完全一样,包括:函数名、函数的返回值类型、参数列表。
4,子类中的函数所抛出的异常必须和父类中被覆写函数所抛出的异常相同,或者是被覆写函数异常的子集,如果父类中被覆写函数没有抛出异常,子类中的函数在覆写时也不能抛出异常。
4.3多态(Polymorphism):
4.3.1什么是多态?
多态,就是一个事物所具有的的多种形态;简单说,就是一个对象,两种形态。
java中对象的多态体现:父类或接口的引用指向子类的对象。
如:
class Person{
intage;
String name;
void show(){
System.out.println("Person show");
}
}
class Studentextends Person{
void show(){
System.out.println("Student show");
}
}
publicclass Demo {
publicstaticvoid main(String[] args) {
Person p=new Student();//这里就体现了对象的多态性。
}
}
4.3.2 多态的好处
提高代码的扩展性,前期定义的内容可以使用后期定义的共性内容。
如:
public class Demo{
public static void main(String []args){
method(new Upan());//调用方法将后期加入的内容创建对象作为参数传入即可使用.
method(new UsbMouse());
}
public static void method(Usb u){//这里体现了多态Usb u=new Upan(); Usb u=new UsbMouse();
u.Open();
u.close();
}
}
interface Usb{
void Open();
void close();
}
class Upan implements Usb{
public void Open() {
System.out.println("Upan open");
}
public void close() {
System.out.println("Upan close");
}
}
//后期定义的内容
class UsbMouse implements Usb{
public void Open() {
System.out.println("UsbMouse open");
}
public void close() {
System.out.println("UsbMouse close");
}
}
4.3.3多态的弊端和前提
弊端:前期定义的内容不能使用后期子类中定义的特有内容.
如:
public class Demo{
public static void main(String []args){
Person p=new Student(23,"张三");//对象的多态特性
p.show();
p.method();//这一句代码是在调用后期子类中定义的特有内容,会报错
}
}
class Person{
int age;
String name;
Person(int age,String name){
this.age=age;
this.name=name;
}
void show(){
System.out.println(this.name+"::"+this.age);
}
}
class Student extends Person{
Student(int age,String name){
super(age,name);
}
void show(){
System.out.println(this.name+"::"+this.age);
}
void method(){//此函数是后期子类中添加的特有功能
System.out.println("姓名:"+this.name+",年龄:"+this.age);
}
}
多态的前提:
1,要有关系:继承或实现. 2,要有覆写.
4.3.4多态的转型
多态的转型分为:向上转型和向下转型
向上转型:可以限定对子类中特有功能的访问.
向下转型:可以使用子类中特有的功能.
public class Demo{
public static void main(String []args){
Person p=new Student();//向上转型,父类引用指向子类对象,只能调用子类和父类中的共性内容.不能调用子类中的特有内容.
p.show();
p.method();//这里如果调用了子类中的特有功能,就会报错.
//如果想调用子类中的特有功能,就需要向下转型:
Student s=(Student)p;//向下转型
s.method();//这里就可以完成对子类特有功能method()函数的调用.
}
}
class Person{
int age=23;
String name="张三";
void show(){
System.out.println(this.name+"::"+this.age);
}
}
class Student extends Person{
void show(){//子类中和父类的共性功能
System.out.println(this.name+"::"+this.age);
}
void method(){//子类中的特有功能
System.out.println("姓名:"+this.name+",年龄:"+this.age);
}
}
4.3.5多态时成员的特点
1,成员变量
public class Demo{
public static void main(String []args){
Fu f=new Zi();//对象的多态性.
System.out.println(f.num);//父类引用调用成员变量.编译、运行均可通过。
}
}
class Fu{
int num=4;//如果Fu类中没有成员变量num,编译时会报错.
}
class Zi extends Fu{
int num=3;
}
//结果:4
编译时(没有创建对象):参考等号左边的引用变量所属类中是否有被调用的成员变量,有,编译通过,没有,编译失败.
运行时(已经创建对象):参考等号左边的引用变量所属类中是否有被调用的成员,并运行该成员变量.
总结:因为在编译时,还没有创建对象编译器在进行语法检查时,会检查引用变量所属类中是否有被调用的成员变量,有就通过,否则编失败,对象创建后,因为Zi类继承Fu类,在创建Zi类对象时,在堆内存中会有两个成员变量num,分别持有this和super引用,Zi类引用变量调用Zi类中的num,Fu类的引用变量调用Fu类中的num.运行时则调用Fu类中的成员变量num,所以,在多态时成员变量的调用都参考等号左边.
2,成员函数
public class Demo{
public static void main(String []args){
Fu f=new Zi();//向上转型,多态特性
f.show();//父类引用型变量调用成员函数,编译、运行均可通过。
f.method();//此句代码在编译时会报错,因为向上转型不能使用子类的特有功能.
}
}
class Fu{
int num=4;
void show(){
System.out.println("Fu show");
}
}
class Zi extends Fu{
int num=3;
void show(){//子类和父类的共性内容
System.out.println("Zi show");
}
void method(){//子类的特有功能
System.out.println("Zi method");
}
}
//结果:Zi show
编译时(没有创建对象):参考等号左边的引用变量所属的类中是否有所调用的成员函数,如果有编译通过,否则,编译失败.
运行时(已经创建对象):参考等号右边的引用变量所属的类中是否有所调用的成员函数,有则运行,没有则再从父类中找,找不到就报错.
总结:编译时,因为没有对象,编译器在进行语法检查时,会根据引用变量所属的类,去查找是否有被调用的成员函数,有则编译通过,否则失败.运行时,因为有了对象,而且是创建了子类的对象,同时子类持有super引用,所以,先从子类中查找被调用的成员函数,如果有就覆写了父类中的成员函数,如果没有,再从父类中查找,找不到就会报错.
3.静态函数
public class Demo{
public static void main(String []args){
F f=new Z();
f.show();//父类引用变量调用静态函数.
}
}
class F{
static void show(){
System.out.println("Fu show");
}
}
class Z extends F{
static void show(){
System.out.println("Zi show");
}
}
//结果: Fu show
因为静态函数,不依赖对象,直接用类名即可调用.
编译时:参考等号左边.有,则编译通过,否则,编译失败.
运行时:参考等号左边,并执行.
4.4关键字 instanceof
作用:用于判断对象的所属类型。返回结果:true or false
如:
public class Demo{
public static void main(String []args){
Zi z=new Zi();
System.out.println(z instanceof Fu);//结果:true
//因为Zi类继承了Fu类,所以Zi类的对象,所属Fu类。
}
}
class Fu{
void show(){
System.out.println("Fu show");
}
}
class Zi extends Fu{
void show(){
System.out.println("Zi show");
}
}
注意:此关键字通常在向下转型时,用于程序健壮性判断。
如:
public class Demo{
public static void main(String []args){
method(new Student(23,"李四"));
}
public static void method(Person p){//这里
p.show();
if(p instanceof Student){//这里使用instanceof关键字来判断s引用变量是否是Student类的对象,如果为true则执行if中的代码,否则结束函数。
Student s=(Student)p;
s.study();
}
}
}
class Person{
int age;
String name;
Person(int age,String name){
this.age=age;
this.name=name;
}
void show(){
System.out.println(this.name+"::"+this.age);
}
}
class Student extends Person{
Student(int age,String name){
super(age,name);
}
void show(){
System.out.println(this.name+"::"+this.age);
}
void study(){
System.out.println("Student study");
}
}
class Worker extends Person{
public Worker(int age, String name) {
super(age, name);
}
void show(){
System.out.println(this.name+"::"+this.age);
}
void work(){
System.out.println("Worker work");
}
}
---------------------- ASP.Net+Android+IOS开发、 .Net培训、期待与您交流! ----------------------