封装/隐藏 : 通过类的访问限定符实现的 private public
继承的意义之一:代码的复用
类的继承是指在一个现有类的基础上去构建一个新的类,构造出来的新类被称为派生类(子类),现有类被称为基类(父类),子类会自动拥有父类的所有可以继承的属性和方法。
在Java中需要用到extends关键字来判断两个类是否具有继承关系。
public class DeriveTest { public static void main(String[] args) { B b1 = new B(); B b2 = new B();
A a = new A(10); b1.test(); } } class A{ protected int a; static{ System.out.println("A static block init."); } { System.out.println("A instance block init."); } public A(){ System.out.println("A()"); this.a = 0; } public A(int a){ System.out.println("A(int)"); this.a = a; } public void show(){ System.out.println("A.show a:" + a); } } /** * 派生类B有两部分 * 1.从基类继承来的成员 * 2.自己定义的成员 * * super和this都必须写在第一行 */ class B extends A{ private int b; private int a; static{ System.out.println("B static block init."); } { System.out.println("B instance block init."); } public B(){ // 如何在派生类中调用基类的构造函数呢? super(); // A() a = 0 System.out.println("B()"); } public B(int data){ super(data); // A(int) a = data System.out.println("B(int)"); } public void show(){ // 作用域不同 show A.show a A.a System.out.println("B.show a:" + super.a); } void test(){ // 测试方法 // 在派生类中,调用基类的方法 super.show(); show();//派生类的方法 } }
在继承中可以继承父类的私有属性和方法,但是不可以调用。
继承结构中,基类和派生类的方法通常有两种关系:重载和重写
* 重载:在一个类作用域中,函数名相同,参数列表不同(在同一个类中)
* 重写:在基类和派生类中,出现返回值相同,函数名相同,参数列表也相同的实例方法(在不同的继承类中)
* 重写指的是派生类方法表中,派生类提供的重写方法,把基类相应的方法的地址给重写了(覆盖了)
基类引用,可以引用派生类对象
*派生类引用,不可以引用基类对象
*把基类和派生类的继承结构,也经常称作从上到下的继承结构,
*继承结构中的类型,只支持从下到上的转换,不支持从上到下
*的转换
* private和protected的区别?
* 1.它们两个修饰的成员,在类的外部都不能访问
* 2.基类的private成员,在派生类中无法访问;基类的protected成员,在派生类中可以访问
一般定义类 - 抽象某个实体的类型
* 但是基类类型 - 不是为了抽象某个实体的类型而定义的,它是为了:
* 1.把派生类公共的成员抽取出来,放到基类里面,通过继承达到代码的复用
* 2.在基类里面给所有派生类保留统一的抽象方法,等待派生类重写,实现多态的使用
* 抽象方法:
* 1.是在实例方法的返回值前面添加abstract,代表该方法不用提供实现
* 2.抽象方法一般放在基类里面
* 3.拥有抽象方法的类,一定得定义成抽象类
* 抽象类:
* 1.类定义的前面添加abstract
* 2.和普通类最大的区别是抽象类不能实例化对象(不可以new 一个抽象类)
* 拥有抽象方法的类 一定是 是抽象类
* 抽象类 不一定拥有 抽象方法
* 什么叫多态???
* 多态就是用基类引用,引用不同的派生类对象,通过基类的引用变量调用同名覆盖方法,这个基类引用引用了哪个派生类对象,就会调用哪个派生类对象重写的方法
* 它的好处就是,在代码设计的时候,不用给每一个派生类都提供相应的入口,而是用基类引用接收所有的派生类对象,然后调用同名覆盖方法,实现多态调用 多态调用的实现(依赖函数的动态绑定实现的)
*
* is a
* 抽象类里面提供的方法,所有的派生类必须都得支持,但是有些方法只有某些派生类支持,其它的派生类是不支持的,我们应该把这些方法定义在_接口has a_里面,表示一种功能约定,表示某个派生类是否 拥有这个
功能,而不是从基类继承来,就必须得实现这个功能
interface IAnimal{ // 写一些动物特有得功能,不是 是个动物都具有这里定义得功能的 int DATA = 10; // public static final void fly(); // 接口的方法默认就是public abstract的 } abstract class Animal { // 拥有抽象方法的类,必须是一个抽象类 protected String name; public Animal(String name) { this.name = name; } // 给所有派生类保留统一的抽象方法,等待派生类去重写 public abstract void bark(); // 抽象方法 } // 猫 - 实体类 class Cat extends Animal{ public Cat(String name) { super(name); } @Override // 在派生类中一定要重写基类继承来的抽象方法 public void bark() { System.out.println(name + "bark: miao miao!"); } } // 狗 - 实体类 class Dog extends Animal{ public Dog(String name) { super(name); } @Override public void bark() { System.out.println(name + "bark: wang wang!"); } } // 猪 - 实体类 class Pig extends Animal{ public Pig(String name) { super(name); } @Override public void bark() { System.out.println(name + "bark: heng heng!"); } } // 鸟 - 实体类 class Bird extends Animal implements IAnimal{ public Bird(String name) { super(name); } @Override public void bark() { System.out.println(name + "bark: ji ji zha zha!"); } public void fly(){ System.out.println(name + " flying!!!"); } } /** * 多态描述: * */ public class 多态 { /** * 请你提供一些API接口,接收不同的动物对象,打印动物的叫声 * 软件设计的终极的原则 “开-闭”原则 * 对扩展开放 对修改关闭 */ /*public static void show(Cat cat){ cat.bark(); } public static void show(Dog dog){ dog.bark(); } public static void show(Pig pig){ pig.bark(); }*/ public static void show(Animal animal){ // animal.bark(); // 通过函数的动态绑定做到的 // 如果这个动物是鸟的话,还要飞一下 if(animal instanceof IAnimal){ ((IAnimal) animal).fly(); } /** * animal -> 对象(对象头 取 方法表地址) -> 方法表中的函数 */ } public static void main(String[] args) { show(new Cat("加菲猫")); show(new Dog("哈巴狗")); show(new Pig("佩奇")); show(new Bird("百灵鸟")); } }
函数绑定:
* 函数的静态绑定和动态绑定是什么?
* 绑定(函数调用)
* invokestatic指令就是在以静态绑定的方法,调用函数
* invokevirtual指令就是在以动态绑定的方法,调用函数
*
* static方法都是静态绑定调用
* 实例方法都是动态绑定调用
*
* 静态绑定,指的是编译时期的绑定,编译阶段,这个方法的调用就是确定好的,永不不会再改变
*
* 动态绑定,指的是运行时期的绑定,就是在编译阶段,此处调用哪个函数,是 不确定的,
*
* final的应用场景有三个:
* 1.final int data = 10; 可以用来定义常量
* 2.final可以修饰类称作密封类,不能再被继承
* 3.final可以修饰类的实例方法,称作密封方法,表示该方法不能在派生类中重写(覆盖)