OOP(Object Oriented Programming) 面对象编程
OOP语言的特征:继承、封装、多态
继承
class A extends B{
}
A继承了B
A:子类(派生类)
B:父类(基类 / 超类)
继承的好处:可以进行代码的复用
Java中一个子类只能继承一个父类(单继承)。
class Animal1{
public String name;
public int age;
public void eat(){
System.out.println(this.name +" eat()");
}
}
class Fish extends Animal1{
public void swim(){ 鱼特有的方法
System.out.println(this.name +" swim()");
}
}
class Bird1 extends Animal1{
public void fly(){
System.out.println("fly");
}
}
public class Test0 {
public static void main(String[] args) {
Fish fish = new Fish();
fish.name = "lala"; //先给name 赋值,后面 继承 并 实现方法时使用所赋的值
fish.eat();//lala eat()
fish.swim();//lala swim()
System.out.println("========");
Bird1 bird1 = new Bird1();
bird1.eat();//调用Animal的eat方法,内部name还没有赋值
bird1.name = "fafa";//null eat()
bird1.fly();//fly
}
}
继承时会拥有父类的属性,同时还会保留自己特有的 方法 、属性。
name被private修饰, 仅在Animal类内使用,
所以Dog1 无法正常访问Animal中的name
※ 对于父类的private的字段和方法,子类可以继承,但不能访问。
除了构造方法,
父类其余字段和方法都会被子类继承
如果要构造子类,需要先帮助父类对象进行构造,调用合适的构造方法。
"super() ---- 调用父类构造方法"
super关键字
在子类内部调用父类方法
class Animal{
protected String name;
public int age;
public Animal(String name){
this.name = name;
}
public void eat(){
System.out.println(this.name +"eat()");
}
}
class Dog extends Animal{
public String sex;
public Dog(String name){
super(name);显示的调用父类的构造方法 来构造父类对象
}
}
子类和父类有同名方法时,如果在子类的方法中直接调用,那么就默认调用子类自己的方法。
加上super关键字,则是调用父类的方法。
super和 this对比
super: 父类对象的引用 | this: 当前对象的引用 |
---|---|
super() 显示调用父类的构造方法 | this() 调用构造方法 |
super.data; 调用父类的成员属性 | this.data; 访问成员变量 |
super.func(); 调用父类的成员方法 | this.func(); 调用成员方法 |
super() 必须放在第一行进行显示
this()也必须放在第一行
继承中执行顺序
class Animal{
public String name;
public int age;
public Animal(String name){
System.out.println("执行了父类的构造函数:Animal(String)");
this.name = name;
}
static{
System.out.println("执行了父类的static{}");
}
{
System.out.println("执行了父类的 实例代码块{}");
}
public void eat(){
System.out.println(this.name +"eat()");
}
}
class Dog extends Animal{
public String sex;
public Dog(String name,String sex){
super(name); //显示的调用父类的构造方法 来构造父类对象
this.sex = sex;
System.out.println("执行了子类的构造函数:Dog(String,String)");
}
static {
System.out.println("执行了Dog子类的static{}");
}
{
System.out.println("执行了Dog子类的实例代码块{}");
}
public void bark(){
System.out.println(super.age);
super.eat();
System.out.println(this.name +" wangwang");
}
}
public class Test {
protected int val = 10;
public static void main(String[] args){
Dog dog = new Dog("lala","男");
System.out.println("=========");
Dog dog1 = new Dog("lala","男");
}
}
运行结果:
执行了父类的static{}
执行了Dog子类的static{}
执行了父类的 实例代码块{}
执行了父类的构造函数:Animal(String)
执行了Dog子类的实例代码块{}
执行了子类的构造函数:Dog(String,String)
=========
执行了父类的 实例代码块{}
执行了父类的构造函数:Animal(String)
执行了Dog子类的实例代码块{}
执行了子类的构造函数:Dog(String,String)
1.父类静态代码块;
2.子类静态代码块;(静态代码块只执行一次)
3.父类实例代码块;
4.父类构造代码块;
5.子类实例代码块;
6.子类构造代码块。
访问修饰限定符
范围 | private | default | protected | public |
---|---|---|---|---|
同一包中的同一类 | √ | √ | √ | √ |
同一包中的不同类 | √ | √ | √ | |
不同包中的子类 | √ | √ | ||
不同包中的非子类 | √ |
default: 默认访问控制权限 (包访问权限)
只有在同一个包内才能访问这个数据。
private < default < protected < public
final关键字
1.表示常量 final int a = 10; |
---|
2. final class A { } 密封类, 说明这个类不能被继承; |
3. final 修饰方法 ,密封方法; |
❀ final 关键字的功能是限制类被继承
❀ final修饰一个变量或者字段的时候,表示常量(不能修改)
❀ final 修饰类时,表示被修饰的类不能被继承
组合
xxx 包含 xx
一个类的实例作为另外一个类的字段
class Student {
}
class Teacher {
}
class School {
public Student[] students;
public Teacher[] teachers;
}
多态
向上转型
class Fish extends Animal{
}
//前面Fish和Animal已经构成了父子类关系
Fish fish = new fish("dudu");
Animal animal = fish;
也可以写成如下方式
// 父类的引用 引用了子类对象
直接赋值
Animal animal = new Fish ("dudu");
子类引用给父类。
animal引用也指向dog引用所指的对象。
class Animal{
public String name;
public int a = 20;
}
class Fish extends Animal{
public int b = 10;
}
public static void main(String[] args) {
Animal animal = new Fish("拉拉");
System.out.println(animal.name);
System.out.println(animal.a);
System.out.println("==============");
// System.out.println(animal.b); //error
}
animal的类型Animal ,所以animal引用只能访问Animal类自己的成员
方法传参
public class Test{
public static void main(String[] args){
Fish fish = new Fish("lala");
feed(fish);
}
public static void feed(Animal animal){
animal.eat("食");
}
}
方法返回
public class Test{
public static void main(String[] args){
Animal animal = findMyAnimal();
}
public static Animal findMyAnimal(){
Fish fish = new Fish("lala");
return fish;
}
}
向下转型
父类对象转成子类对象
Animal animal = new Fish("dudu");
//先判断animal1 是不是Fish的实例
if(animal1 instanceof Dog) {
//向下转型 先要进行向上转型
Fish fish = (Fish)animal;
fish.swim();
}
向下转型 , 先要进行向上转型
向下转型非常不安全,不建议使用
抽象类
adstract class shape {
public abstract void dram();
}
父类Shape中的draw方法没有实际工作,
像这种没有实际工作的方法,可以把它设计成一个抽象方法。包含抽象方法的类被称为抽象类。
△抽象类可以被继承,也可以发生向上转型,动态绑定。
△抽象类不可以被实例化。
△抽象类当中的方法一定要被子类重写。
△抽象类存在的意义就是为了被继承,因为不能被实例化。
△如果是抽象类继承了一个抽象类,那么可以不重写这个抽象方法。但是如果这个抽象类再次被一个普通的类继承,那么一定要重写。
△抽象方法不能是private。
△可以包含普通方法。
△抽象类不能被final修饰。
接口
interface IFlying {
void fly();
}
interface IRunning {
void run();
}
使用interface定义一个接口
○接口当中的方法默认是public abstract 不能有具体的实现。
○接口不能实例化。
○接口当中的方法默认是public static final 。
○类和接口直接关系是implements,此时接口当中的所有方法,都要被重写。
○也可以发生向上转型,运行时绑定(动态绑定)。
○JDK1.8 开始,接口当中的方法可以有具体的实现,但这个方法一定要被default 修饰。
○在Java 当中一个类可以实现多个接口。
○类和接口是 implements,接口和接口之间是 extends。
(内容持续完善中)