java自学-面向对象三大特性

 面向对象有三大特性,分别是:封装、继承和多态。
封装:面向对象的封装就是把描述一个对象的属性和行为的代码封装在一个类中,有些属性是不希望公开的,或者说被其他对象访问的,所以我们使用private修饰该属性,使其隐藏起来;类中提供了方法(用public修饰),常用的是get、set方法,可以操作这些被隐藏的属性,其他类可以通过调用这些方法,改变隐藏属性的值!
封装是保证软件部件具有优良的模块性的基础,封装的目标就是要实现软件部件的“高内聚、低耦合”,防止程序相互依赖性而带来的变动影响。在面向对象的编程语言中,对象是封装的最基本单位,面向对象的封装比传统语言的封装更为清晰、更为有力。

封装实现:
1. 成员变量用private 关键字来修饰。
2. 提供对应的 getXxx 方法 、 setXxx 方法访问成员变量。
 
private的含义
1. private是一个权限修饰符,代表最小权限。
2. 可以修饰成员变量和成员方法。
3. 被private修饰后的成员变量和成员方法,只在本类中才能访问。

举例:把姓名和年龄封装到人的类中,name和age用private修饰,提供public的set和get方法。外部想操作name,age字段,只能通过set和get方法

public class People{ 
private String name; 
private int age; 
public void setName(String name) { 
this.name = name;
 }
public String getName() { 
return name; }
public void setAge(int age) {
this.age = age; 
}
public int getAge() { 
return age;
}
}

继承:在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,使用extends关键字实现继承;子类中可以加入若干新的内容,或修改原来的方法使之更适合特殊的需要,这就是继承。继承是子类自动共享父类数据和方法的机制,这是类之间的一种关系,提高了软件的可重用性和可扩展性。

继承的格式:

class 父类 { ... }

class 子类 extends 父类 { ... }

举例:

/** 定义父类*/ 
class Fu{ 
String name; // 定义name属性 
// 定义员工的工作方法 
public void work() { 
System.out.println("尽心尽力地工作"); 
} 
}

/** 定义讲师类Teacher 继承 员工类Employee */ 
class Zi extends Fu{
 // 定义一个打印name的方法 
public void printName() { 
System.out.println("name=" + name); }
 }

/** 定义测试类 */
 public class Demo01 { 
public static void main(String[] args) { 
// 创建一个讲师类对象 
Zi zi = new Zi(); 
// 为该员工类的name属性进行赋值 
zi.name = "小明"; 
// 调用该员工的printName()方法
 zi.printName(); // name = 小明 
// 调用Teacher类继承来的work()方法
 zi.work(); // 尽心尽力地工作 
} 
}
子类可以直接访问父类中的非私有的属性和方法。
Fu 类中的成员变量是非私有的,子类中可以直接访问。若Fu 类中的成员变量私有了,子类是不能直接访问的。
如果子类中出现和父类重名的成员变量,子对象调用时会调用自己的属性。如果子类想调用父类的同名属性,可以用super.XXX调用。
成员方法重名——重写(Override)
如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)。即子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),子类会覆盖父类,也称为重写或者复写。声明不变,重新实现。

举例:

class Fu { 
public void show() { 
System.out.println("Fu show"); 
} 
}

class Zi extends Fu { 
//子类重写了父类的show方法
 public void show() {
//
子类可以根据需要,定义特定于自己的行为。既沿袭了父类的功能名称,又根据子类的需要重新实现父类方法,从而进行扩展增强。
 System.out.println("Zi show");
 } 
}

public class Demo02{ 
public static void main(String[] args) {
 Zi z = new Zi(); 
// 子类中有show方法,只执行重写后的show方法 
z.show(); // Zi show 
}
}
注意事项
1. 子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
2. 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。

父类的构造方法不能继承也不能重写。

1. 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。
2. 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个 super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。
super和this的含义
super :代表父类的存储空间标识(可以理解为父亲的引用)。
this :代表当前对象的引用(谁调用就代表谁)。
this.成员变量 ‐‐ 本类的 
super.成员变量 ‐‐ 父类的 

this.成员方法名() ‐‐ 本类的 
super.成员方法名() ‐‐ 父类的
继承的特点
1. Java只支持单继承,不支持多继承。
一个类只能有一个父类,不可以有多个父类
2. Java支持多层继承(继承体系)。
顶层父类是Object类。所有的类默认继承Object,作为父类。
抽象类
父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类。
使用 abstract 关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。如果一个类包含抽象方法,那么该类必须是抽象类。
举例:
public abstract class A{
 public abstract void run(); 
}
继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该父类的抽象方法.
举例:
public class Cat extends A{
 public void run (){
 System.out.println("小猫在墙头走~~~");
 } 
}

public class CatTest { 
public static void main(String[] args) { 
// 创建子类对象 Cat c = new Cat(); 
// 调用run方法 c.run(); 
} 
}
输出结果: 小猫在墙头走~~~
此时的方法重写,是子类对父类抽象方法的完成实现,这种方法重写的操作,也叫做实现方法。
 
注意事项
1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。
 
接口
接口是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么接口的内部主要就是封装了方法。它与定义类方式相似,但是使用 interface 关键字。

 接口不能创建对象,但是可以被实现( implements ,类似于被继承)。一个实现接口的类(可以看做是接口的子类),需要实现接口中所有的抽象方法,创建该类对象,就可以调用方法了。

举例:

public interface InterFaceName { 
public void method(); 
}
类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用 implements 关键字。
格式:
class 类名 implements 接口名 { 
// 重写接口中方法【必须】
  }

举例:

//定义接口
public interface People{
 // 定义抽象方法 
public abstract void eat(); 
public abstract void sleep(); 
}

//定义实现类
public class XiaoMing implements People{ 
@Override public void eat() {
 System.out.println("吃东西"); 
}
@Override 
public void sleep() {
 System.out.println("晚上睡");
 }
 }

//定义测试类
public class InterfaceDemo { 
public static void main(String[] args) { 
// 创建子类对象 
Peoplel p = new XiaoMing(); 
// 调用实现后的方法 
p.eat(); 
p.sleep(); 
} 
}
输出结果: 吃东西 晚上睡
在继承体系中,一个类只能继承一个父类。而对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现。并且,一个类能继承一个父类,同时实现多个接口。
格式:
class 类名 [extends 父类名] implements 接口名1,接口名2,接口名3... { 
// 重写接口中抽象方法【必须】 
 }
当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的默认方法重名,子类就近选择执行父类的成员方法。
接口中,无法定义成员变量,但是可以定义常量,其值不可以改变,默认使用public static final修饰。
 匿名内部类 :是内部类的简化写法。它的本质是一个带具体实现的父类或者父接口的子类对象。开发中,最常用到的内部类就是匿名内部类了。匿名内部类必须继承一个父类或者实现一个父接口。
格式:
new 父类名或者接口名(){
// 方法重写
@Override
public void method() {
// 执行语句
}
};

举例:

//定义接口
public abstract class FlyAble{

public abstract void fly();

}
 
//创建匿名内部类
public class InnerDemo {
public static void main(String[] args) {
/*
1.等号右边:是匿名内部类,定义并创建该接口的子类对象
2.等号左边:是多态赋值,接口类型引用指向子类对象
*/
FlyAble f = new FlyAble(){
public void fly() {
System.out.println("我飞了~~~");
}
};
//调用 fly方法,执行重写后的方法
f.fly();
}
}
 

 

多态:多态就是在声明时使用父类或接口,在实现或调用时使用具体的子类或实现类;即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性,多态增强了软件的灵活性和扩展性。这里可以举个例子,比如声明时使用的是动物类,调用时传递的是一个猫类(动物类的子类)的对象,具体执行父类里动物——吃的方法时,实际执行的是猫——吃的方法。

多态体现的格式:
父类类型 变量名 = new 子类对象; 
变量名.方法名();

Fu f = new Zi();
 f.method();
父类类型:指子类对象继承的父类类型,或者实现的父接口类型。
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是子类重写后方法。
 多态使用父类指定类型,具体实现要看是哪个子类的对象。
举例:
Fu f = new Zi();//实现类为Zi
Fu f1 = new Zi1();、、实现类为Zi1

public void method(Fu f){
.....
//方法入参为Fu,对象f,f1都可以传入,这就是多态的一种应用
//父类定义一个方法,两个子类都有自己的实现,传入哪个子类,就调用哪个子类的方法
}

 

引用类型转换
多态的转型分为向上转型与向下转型两种:
向上转型
向上转型:多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的。当父类引用指向一个子类对象时,便是向上转型。
使用格式:
父类类型 变量名 = new 子类类型(); 
如:Animal a = new Cat();
向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。
使用格式:
子类类型 变量名 = (子类类型) 父类变量名;
 如:Cat c =(Cat) a;

 



posted @ 2020-06-11 18:21  自习小夫子  阅读(233)  评论(0编辑  收藏  举报