一、面向对象特征——多态
- 多态含义:多种状态
- 同一个父类,可以表示不同的子类对象,状态就不同了
- 父类的引用指向子类对象,两类之间必须是继承关系
- 把子类类型转为父类类型,同一个父类在不同时候,表示不同状态(子类)
代码示例:
public abstract class Animal extends Object {
private String name;
private int age;
int num = 10;
public abstract void eat();
public void sleep(){
System.out.println("动物睡觉");
}
public static void show(){
System.out.println("animal中的show()");
}
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;
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse(){
}
}
public class Dog extends Animal{
int num = 20;
@Override
public void eat() {
System.out.println("狗吃骨头");
}
@Override
public void sleep() {
System.out.println("睁着眼睛睡觉");
}
public static void show(){
System.out.println("dog中的show()");
}
public void lookHome(){
System.out.println("狗看门");
}
}
public class Person {
/*
人喂动物
使用父类Animal,可以接收任意的子类(猫,狗)
,只需要定义一个方法,处理不同的子类
提高程序的扩展性(只需要添加其他的类,大象,企鹅 )
*/
public void feedAnimal(Animal animal){
animal.eat();
//判断animal变量,实际运行时表示的是否是Dog类型
if(animal instanceof Dog){
Dog dog = (Dog)animal;
dog.lookHome();
}
}
/* *//*
人喂狗, 由于参数类型是Dog, 只能接收Dog类型,为每种动物定义一个方法,
不便于程序的扩展,每添加一种类型,就需要修改代码
*//*
public void feedDog(Dog dog){
dog.eat();
}
*//*
人喂猫
*//*
public void feedCat(Cat cat){
cat.eat();
}*/
}
public static void main(String[] args) {
/*
new哪个类的对象,就用哪个类的类型表示,一个个都是孤立的,独立的
Dog dog = new Dog();
Cat cat = new Cat();
Person person = new Person();
person.feedDog(dog);
person.feedCat(cat);
*/
/*
多态--多种状态
同一个父类,可以表示不同的子类对象,状态就不同了.
父类的引用指向子类对象,两个类之间必须是继承关系
把子类类型转为父类类型,同一个父类在不同时候,表示不同状态(子类)
*/
Animal dog = new Dog();
Animal cat = new Cat();
Person person = new Person();
person.feedAnimal(dog);
person.feedAnimal(cat);
}
}
注意:
- 注意成员调用时,分为编译期间和运行期间
- 编译期间: 写代码时 由于类型上升为了父类类型,所以只能调用到父类中定义成员
- 运行期间: 运行代码时,实际调用的是子类中重写的方法
- 对应非静态成员方法:编译看左边, 运行看右边
- 对于静态成员方法和成员变量:编译看左边,运行也是看左边
代码示例 :
public static void main(String[] args) {
/*
多态注意事项:
注意成员调用时,分为编译期间和运行期间
编译期间: 写代码时 由于类型上升为了父类类型,所以只能调用到父类中定义成员
运行期间: 运行代码时,实际调用的是子类中重写的方法
对应非静态成员方法:
编译看左边, 运行看右边
*/
Animal dog = new Dog();
Animal cat = new Cat();
dog.eat();
cat.eat();
dog.sleep();//对于子类如果没有重写父类中的方法,那么调用的是子类对象中父类的方法
cat.sleep();
/*
对于静态成员方法和成员变量
都是编译看左边,运行也是看左边
*/
dog.show();
System.out.println(dog.num);
}
思考:为了实现多态性,我们将子类类型向上转为了父类类型,但是一旦类型上升为父类类型,那么就调用不到子类中特有的方法。
解决办法:向下转型,把父类类型转为子类类型
代码示例:
public static void main(String[] args) {
/*
为了实现多态性,我们将子类类型向上转为了父类类型,
但是一旦类型上升为父类类型,那么就调用不到子类中特有的方法.
这就是多态在某种情况下的缺点.
解决办法:
就行向下转型,把父类类型转为子类类型
*/
//Dog d = (Dog)dog;
// d.lookHome();
Person p = new Person();
p.feedAnimal(dog);
p.feedAnimal(cat);
}
二、final关键字
- final关键字 可以修饰类,方法,参数,成员变量
- final不能修饰抽象类和接口, 因为final修饰的类不能被继承
- final修饰方法,修饰后方法不能被子类重写
- final修饰方法的参数,在方法内部,就不能修改参数值
- final修饰成员变量时有以下两种情况:
情况1: 在编码时,值就确定了,就直接进行赋值,此种情况最好加上static关键字,让其在内存中只有一份
情况2: 每一个对象中都有一个常量,必须在构造方法中为常量进行初始化,一旦初始化后,值都不能更改
代码示例:
/*
final关键字 可以修饰类,方法,参数,成员变量
final不能修饰抽象类和接口, 因为final修饰的类不能被继承
final修饰方法,修饰后方法不能被子类重写
final修饰方法的参数,在方法内部,就不能修改参数值.
final修饰成员变量,
*/
public class Demo {
//情况1: 在编码时,值就确定了,就直接进行赋值,此种情况最好加上static关键字,让其在内存中只有一份.
static final int num = 10;
//情况2: 每一个对象中都有一个常量,必须在构造方法中为常量进行初始化,一旦初始化后,值都不能更改
final int count;
public Demo(int count) {
this.count = count;
}
public final void test(final int a){
//a = 10;
}
public static void main(String[] args) {
/*Demo demo = new Demo();
demo.test(20);
demo.test(30);*/
//demo.num = 30;
new Demo(10);
new Demo(20);
new String("ssss");
new String("aaaa");
}
}
三、接口
- 接口是一种更为彻底地抽象
- 接口是不能被创建对象的
- jdk8之后接口可以定义4种内容:
- 静态常量
- 抽象方法
- 惊涛方法(jdk8之后才开始有的)
- 默认方法(jdk8之后才开始有的)
代码示例:
/*
接口:
是一种更为彻底的抽象,主要用来定义功能
接口是不能被创建对象的.
jdk8之后接口可以定义4种内容:
1.静态常量
2.抽象方法
3.静态方法(jdk8之后才开始有的)
4.默认方法(jdk8之后才开始有的)
*/
public interface MyInterface {
int num = 10; // public static final int num = 10 静态常量
void test(); // public abstract void test(); 抽象方法
//接口中定义静态方法,通过接口名直接访问
public static void staticMethod(){
}
//默认方法,需要类继承,然后通过子类调用
public default void test1(){
}
}
public class Test {
public static void main(String[] args) {
System.out.println(MyInterface.num);
MyInterface.staticMethod();
}
}
注意事项:类实现接口,一个类可以实现多个接口
代码示例:
import java.io.Serializable;
/*
类实现接口,一个类可以实现多个接口
MyInterfaceImpl类就是MyInterface接口的实现类
*/
public class MyInterfaceImpl implements MyInterface {
@Override
public void test() {
}
public static void main(String[] args) {
}
}