目录
封装
封装的概念
封装:将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。
封装的好处
- 只能通过规定好的方法才能访问
- 方便加入控制语句
- 隐藏类的实现细节
- 方便修改实现
具体的表现方式是使用get/set方法来实现
public class Demo{
private int id;
public int getID(){
return id;
}
public int setID(int id){
this.id=id;
}
}
继承
继承的概念
继承:继承是从已有的类中派生出新的类,新的类能吸收已有类的属性和行为,并在此基础上拓展自己新的属性以及行为。
拿JAVA为例子:
- 在JAVA中使用extends关键字来表示继承关系。
- JAVA不支持多继承,只能单继承,单继承使JAVA的继承关系很简单,一个类只能有一个直接父类。
- 继承之后子类可以调用父类的所有非私有属性和非私有方法。
继承是代码重用的一种方式
继承的形式
[访问权限修饰符] [修饰符] 子类名 extends 父类名{子类体}
public class Animal{
public void eat(){}
}
public class Dog extends Animal{
public void play(){}
}
//子类对象可以直接调用父类的方法,强调复用性
Dog dog = new Dog ();
dog.eat();
Dog类是Animal类的子类,Animal类是Dog类的父类
Dog类是Animal类的派生类,Animal类是Dog类的基类
继承的传递性
C类从B类继承,B类又从A类继承
那么C类就具有B类和A类的所有非私有属性和非私有方法
当一个没有继承任何一个类时,jvm会默认让类继承Object类Object是java为所有类提供的基类
public class A {
String name;
public A(String name){
this.name=name;
}
public void speak(){
System.out.println("A说话");
}
public void cry(){
System.out.println("A哭");
}
}
class B extends A{
public B(String name){
super(name);
}
@Override
public void cry() {
System.out.println("B哭");
}
}
class C extends B{
public C(String name){
super(name);
}
@Override
public void cry() {
System.out.println("C哭");
}
}
public class Test {
public static void main(String[] args) {
A a=new A("a");
B b=new B("b");
C c=new C("c");
System.out.println(a.name);
System.out.println(b.name);
System.out.println(c.name);
c.speak();//C传递继承可以继承到A中的方法
c.cry();//重写父类中的方法,如果没有继承就不能使用同样的方法名
b.cry();
a.cry();
}
}
继承中的构造方法
子类构造方法会先调用父类构造方法
使用super关键字调用父类任意一个构造方法,必须写在构造方法的第一行
如果子类的构造方法中没有显式地调用基类构造方法,则系统默认调用基类无参数的构造方法。
super关键字用途
使用super关键字访问父类成员
-
用super.成员变量名来引用父类成员变量
-
用super.方法名(参数列表)访问父类的方法。
-
用super.构造方法(参数列表)访问父类构造方法。
误区: 不要把super误认为是父类对象.在创建子类对象时,
不会创建父类对象.
只会将父类中的信息加载到子类对象中存储.
方法的重写(OverRide)
当父类的方法实现不能满足子类需求时,可以对方法进行重写( override)
在子类中可以根据需要对从基类(父类)中继承来的方法进行重写。
方法重写规则
方法名相同、参数列表相同
返回值类型相同
访问权限不能小于父类权限
<u>注意:构造方法, 静态方法不能重写,成员变量不存在重写
</u>
方法重载的定义
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
“两同一不同”
-
同一个类、相同方法名
-
参数列表不同:参数个数不同,参数类型不同
注:判断是否为重载,跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系*
重写与重载区别
重载是定义相同的方法名,传入的参数不同。重写是子类重写父类中的方法。
重载是在一个类中。重写是发生在子类与父类之间。
重载是编译时的多态性(在编译时可以根据方法签名就判断出调用的什么方法)。重写是运行时的多态性(重写在编译时是无法看出使用的什么方法的)。
Java实现多态的三个必要条件:继承、方法重写、向上转型
有了对象的多态性之后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
编译与运行
编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。
抽象类
抽象方法
抽象方法是一种特殊的方法:
它只有声明,而没有具体的实现.
抽象方法必须用abstract关键字进行修饰
抽象类的定义
-
如果一个类中没有足够的信息来描绘一个具体的对象,这样的类就是抽象类。(包含抽象方法,有抽象方法的类一定是抽象类,但抽象类中不一定有抽象方法)
-
抽象类除了不能实例化对象以外,类的其他功能依然存在,成员变量,成员方法和构造方法。
-
用abstract修饰的类就是抽象类。如果某个类中包含有抽象方法,那么该类就必须定义成为抽象类。
抽象类的特点
抽象类不能被实例化,但可以有构造方法,因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。
抽象类只能用作基类,表示的是一种继承关系。继承抽象类的非抽象类必须是实现其中的所有抽象方法,而已实现方法的参数、返回值和抽象类中的方法一样。否则,该类也必须声明为抽象类。
使用关键字abstract定义抽象类,一般语法:
[访问权限] abstract class 类名 {
成员列表
}
public abstract class Shapes {
public abstract void draw();
}
public abstract class Shapes {
public void draw(){
//具体代码
}
}
abstract class Person {
String name;
String country;
void say(){
System.out.println("人说话");
}
}
class Chinese extends Person{
public void say(){
//重写抽象方法
System.out.println("中国人说话");
}
}
public class Test {
public static void main(String[] args) {
Chinese c=new Chinese();
System.out.println(c.name);
c.say();
}
}
多态
多态:同一种事物,在不同时刻表现不同的状态
多态存在的三个必要条件:
-
要有继承(包括接口的实现)(前提条件)
-
要有重写(前提条件)
-
父类引用指向子类对象
public class Test{
public static void main(String[] args){
Dog xh=new Dog();
/*
编译期间 a.eat() a的类型是Animal类,调用的是抽象的eat()
运行期间 a指向的是一个Dog对象,运行的是Dog中重写的eat()
针对于非静态成员方法:
编译期间看左边(写代码时) 运行期间看右边 */
Animal a=new Dog();
a.eat();//非静态成员方法(抽象方法)
a.sleep();//sleep()为父类Animal(抽象类)中的非静态方法
/*
针对静态方法:
编译期间看左边 运行期间还是看左边 */
a.play();//play()为父类(抽象类)中的静态方法
/*
针对成员变量:
编译期间看左边 运行期间还是看左边 */
System.out.println(a.age);//age为父类中的成员变量
//a为父类中的变量,因此成员变量只能调用父类中的
}
}//父类为抽象类
主要还是看清就近关系!
多态调用成员方法:1.子类中重写父类的方法2.父类中本来就有的方法3.父类中的静态方法
多态直接输出成员变量:1.父类中的成员变量(没有就不能输出)
多态的用法
可以避免反复的调用而造成的繁琐。
public class Test3 {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
Monkey monkey = new Monkey();
Test3 t = new Test3();
t.feedAnimal(dog);
t.feedAnimal(cat);
t.feedAnimal(monkey);
}
/*
喂动物 将对象传入,调用动物中的方法
判断animal中实际传入的类型是什么
父类引用 instanceof 具体的子类类型
instanceof 判断父类引用实际表示的对象 是不是 指定类型
*/
public void feedAnimal(Animal animal){
animal.eat();
System.out.println(animal instanceof Dog);
//判断传入的对象是否属于Dog类型,返回的是boolean类型
if(animal instanceof Dog){
Dog dog = (Dog)animal;
dog.play();
}
}
多态转型
自动转型:
子 继承 父
向上类型:子类自动转型(上升型)为父类类型
Animal dog=new Dog();
强制转型:
向下转型:父类类型转为子类自己的类型(为了使用子类中特有的方法)
优点:父类引用表示子类对象,提升程序的扩展性
缺点:父类类不能调用子类中特有的方法