面向对象的三大特征
-
面向对象三大特性:封装、继承、多态。
-
封装:尽可能隐藏对象的内部实现细节,控制对象的修改及访问的权限。
-
封装的好处是保证数据的安全性,提供清晰的对外接口,类内部实现可任意修改,不影响其他类。
-
-
继承: 继承是指子类可以继承父类的属性和方法,或者重新定义、追加属性和方法等。
-
继承是一种“is-a”关系,代表了子类和父类之间的包含关系。子类除了具备父类的所有特性外,还可以定义新的特性。
-
继承的工作方式是定义父类和子类,或叫做基类和派生类,其中子类继承父类的所有特性。
-
在一组相同或类似的类中,通过继承抽取出定义在父类中共性的特征和行为,实现重用。
-
-
多态:父类引用指向子类对象,子类对父类的方法进行重写,从而产生多种形态。
-
多态是指允许不同类的对象对同一消息作出响应,但都要用自己的代码来执行。
-
多态性包括参数化多态性和包含多态性。
-
多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。
-
封装
特征2:继承
继承的概述
-
继承允许一个类(子类)继承另一个类(父类)的属性和方法
-
继承可以提高代码的复用性,减少冗余。
继承的基本使用
-
继承主要是通过
extends
关键字来实现-
创建父类
public class Parent { String name; int money; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } public void say(){ System.out.println("我是"+this.name+",我有"+this.money); } }
-
创建子类
public class Child extends Parent{ int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
-
测试代码
public static void main(String[] args) { //创建父类对象 Parent parent = new Parent(); parent.setName("父类"); parent.setMoney(100); //创建子类对象 Child child = new Child(); child.setName("子类"); //child.setMoney(200); //调用方法 parent.say(); child.say(); }
-
继承的限制
-
在继承过程中的可见性(但是具体的属性还是被继承下来了,只是可不可见的问题)
-
private:对于父类和子类都不可以用
-
default:在同包下,可以用使用
-
protected:在不同包的,子类中可用
-
public:所有情况下都可以使用
修饰符 在本类中 同一个包下的其他类里 任意包下的子类型 任意包下的任意类型 private T defaul T T protected T T T public T T T T
-
-
Java支持多层继承,但不支持多继承,即子类只能继承一个父类。
Object类
Object类是java所有类的祖宗类,我们写的任何一个类,其实都是object的子类或孙子类。
继承中构造方法的使用
-
子类继承父类之后,子类在被new出来对象的时候,是需要调用父类的构造方法的。默认调用的是无参的构造方法
-
构造方法是不可以被继承的,子类必须要调用父类的构造方法
-
一旦父类提供一个带有参数的构造方法之后,默认的无参构造方法就失效了。解决方案如下:
-
方案1:父类必须要写一个无参的构造方法
-
方案2:父类没有无参的构造方法,那么在子类中的构造方法中,就必须要通过super调用父类的构造方法。而且必须super构造方法必须要写在第一行,其他的代码必须要在super之后重点:父类添加有参构造器,默认构造器就没有了,子类继承父类,那么子类里的有参或者无参构造器都会失效或报错,在子类中添加super()/super(实参)
-
-
方案2的案例代码
-
父类代码
public class ParentSprite { String name; int blood; int power; public ParentSprite(String name, int blood, int power) { this.name = name; this.blood = blood; this.power = power; } }
-
子类代码,必须在构造方法中通过super调用父类的构造方法
public class Hero extends ParentSprite{ //特有的皮肤属性 String skin; public Hero(String name, int blood, int power,String skin) { //在子类构造方法中,必须调用父类的构造方法 //默认情况下,如果不直接写,那么机会默认调用super() super(name, blood, power); this.skin = skin; } }
-
super关键字
-
super关键字可以调用父类的属性,方法和构造方法
-
super后面加上了
.
是调用属性或者是方法的 -
super后面直接加
()
调用父类的构造方法的
-
-
super和this的用法很像,区别就是this调用的是本类的属性和方法,super调用的是父类的
方法重写
-
分析:当父类提供的方法无法满足子类需求时,可在子类中定义和父类相同的方法进行重写(Override)。
-
方法重写原则:
-
方法名称、参数列表、返回值类型必须与父类相同。
-
访问修饰符可与父类相同或是比父类更宽泛。
-
-
方法重写的执行:
-
子类重写父类方法后,调用时优先执行子类重写后的方法。
public class TestOverride { public static void main(String[] args) { Dog dog = new Dog(); dog.eat();//狗在吃骨头(覆盖后,优先执行子类覆盖之后的版本) Cat cat = new Cat(); cat.eat();//猫在吃鱼 } } class Animal{ String breed; int age; String sex; public void eat() { System.out.println("动物在吃..."); } public void sleep() { System.out.println("动物在睡..."); } } class Dog extends Animal{ String furColor; @Override //子类中定义和父类相同的方法进行覆盖 public void eat() { System.out.println("狗在吃骨头..."); } @Override public void sleep() { System.out.println("狗在趴着睡..."); } @Override public void run() { } } class Cat extends Animal{ } class Fish extends Animal{ }
-
-
重写和重载的区别
-
重写 (Override):子类重新定义父类中已有的方法。重写方法必须与被重写的父类方法有相同的方法名称、返回类型和参数列表。
-
重载 (Overload):在同一个类中定义多个名称相同但参数列表不同的方法。重载方法必须要不相同参数列表(参数的数量或类型);返回类型和访问权限可以不同。
方法重写的其他注意事项
1.使用@Override注解
2.子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限(public > protected > default)
3.重写的方法的返回值类型,要与被重写方法返回值类型一只或者小
4.私有方法,静态方法不能被重写(private ,static)
二.子类访问的特点
1.在子类方法中访问其他成员(成员变量,成员方法),时按照就近原则
package com.Extends; public class Test { public static void main(String[] args) { B b = new B(); b.print3(); } } public class A { //公开成员 public String name = "父类名字"; public void printl(){ System.out.println(name); } //私有成员 private int j; private void println(){ System.out.println("私有方法"); } } public class B extends A{ public String name = "子类名字"; //子类可以继承父类的非私有成员 public void print3(){ String name = "方法内的子类名字"; System.out.println(super.name); } }
1.访问成员变量
当想访问子类成员变量,可以加this来使用,this表示指定某个成员变量,this.naem去子类中找name**
当想访问父类成员变量,可以用super来使用,super.name,去父类中找name
2.访问成员方法
也是按照就近原则、
当想访问父类成员方法,可以用super来使用,super.showMethod(),去父类中找showMethod方法
super的使用
package com.Super; public class Teacher extends People{ private String skill; public Teacher(String name,int age,String skill) { super(name,age); this.skill = skill; } public String getSkill() { return skill; } public void setSkill(String skill) { this.skill = skill; } } class People{ private String name; private int age; public People(String name,int age){ this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
-
补充知识:this(...)调用兄弟构造器
可使用兄弟里的内容,优化代码。
-
方法重写