class A{
public static int a = 10;
public static void fun(){
System.out.println("hello");
}
}
class B extends A{
public void fun2(){
a = 200;
System.out.println(a);
}
}
public class ExtendsQuestion {
public static void main(String[] args) {
B b = new B();
System.out.println(b.a); //输出10
b.fun(); //输出hello,如果B中也有fun方法,则输出的是fun方法中的结果
b.fun2(); //输出200
System.out.println(b.a); //输出200
}
}
二、多态向下转型 1、多态的前提: 1)、要有继承的关系 2)、子类要重写父类中的方法 3)、要有父类的引用指向子类对象 2、多态的弊端: 1)、多态无法使用子类特有的方法 如果就要使用子类特有的功能,能否使用? 能 2)、怎么使用呢? a、创建对应的子类并调用方法 可以,但是不推荐,很多时候会占用堆内存空间 b、java提我们考虑到了这一点,提供了一个技术给我们使用:向下转型 把父类的引用强制转换成子类的引用 子类类名 变量名 = (子类类名)父类的引用 3、多态转型 对象之间转型的问题: 1)、向上转型 其实就是多态创建对象的写法 Fu f = new Son(); 2)、向下转型 Son s = (Son)f; 3)、类比基本数据类型之间的强转: int a = 10; byte b = (byte)a; 4)、向下转型的注意事项: 要求必须是存在继承关系的
class Father{
public void fun(){
System.out.println("这是父类中的fun方法");
}
}
class Son extends Father{
public void fun(){
System.out.println("这是子类中的fun方法");
}
public void show(){
System.out.println("这是子类中特有的show方法");
}
}
class Demo{
}
public class PolymorphicDemo{
public static void main(String[] args) {
// Son2 son2 = new Son2(); //没有学习转型之前调用子类
// son2.show();
//多态创建子类对象(向上转型)
Father2 f = new Son2();
f.fun();
//多态中的向下转型
Son2 s = (Son2)f;
s.show(); //访问子类的show()方法
// Demo类与Father2类不存在继承的关系,所以不能转型
// Demo d = (Demo)f;
}
}
4、多态向下转型条件
1)、要有继承关系
2)、要有方法重写
3)、要有父类的引用指向子类对象
三、抽象类 1、抽象的表述: 我们之前所说的猫,狗,猪,羊驼,熊猫等等都是动物的具体的例子,而动物本身是一个抽象的 概念,而我们之前是将动物写成了一个类,而类又可以创建对象,但是呢,实际上抽象的东西本身应该不能 实例化,并且动物这个概念中吃的方法,以及动物共有的方法本身也是一个不具体的方法, 我们在今天之后,把一个不具体的功能,叫做抽象方法,而如果说一个类中包含有抽象方法的时候, 这个类叫做抽象类。 2、抽象类的特点: 1)、抽象类和抽象方法要用abstract关键字修饰 修饰类 放在class前面 举例: abstract class Animal3{} 修饰方法 放在访问权限修饰符的后面 举例: public abstract void eat(); 2)、有抽象方法的一定是抽象类,抽象类不一定有抽象方法,具体的类中不能有抽象方法 3)、抽象类不能被实例化 既然不能被实例化,那写在抽象类中具体的方法怎么去调用呢? 抽象类如果创建呢? 利用多态的形式,通过具体的子类实例化去调用方法 4)、如果继承抽象类是一个具体的类,要重写抽象类所有的抽象方法 如果是一个抽象类继承抽象类,不需要重写抽象类中的方法
//定义了一个抽象类,叫Animal3
abstract class Animal3{
//注意:
// 抽象方法没有方法体{},连大括号都没有,直接以分号结尾
//抽象方法不能有主体
//public abstract void eat(){};
public abstract void eat();
public void fun(){
System.out.println("这是抽象类中的具体实现的fun方法");
}
}
class Dog3 extends Animal3{
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
abstract class Demo2 extends Animal3{
}
public class AbstractDemo1 {
public static void main(String[] args) {
//Error:(46, 21) java: com.shujia.wyh.day16.Animal3是抽象的; 无法实例化
//Animal3 a = new Animal3();
//使用抽象多态的形式创建
Animal3 a = new Dog3();
a.eat();
a.fun();
}
}
3、抽象类举例
/*
在抽象的动物类中定义两个抽象方法。吃饭和睡觉。
*/
abstract class Animal4{
//定义一个抽象方法吃饭,不给出具体实现
public abstract void eat();
//定义一个抽象方法睡觉,不给出具体实现
public abstract void sleep();
}
class Dog4 extends Animal4{
@Override
public void eat() {
System.out.println("狗吃肉");
}
@Override
public void sleep() {
System.out.println("狗侧着睡");
}
public void lookDoor(){
System.out.println("看门");
}
}
class Cat4 extends Animal4{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫趴着睡");
}
}
public class AbstractTest1 {
public static void main(String[] args) {
//使用抽象多态创建第一个对象
Animal4 a = new Dog4();
a.eat();
a.sleep();
//a.lookDoor();
Dog4 d = (Dog4)a;
d.lookDoor();
//使用抽象多态创建第二个对象
Animal4 a2 = new Cat4();
a2.eat();
a2.sleep();
}
}
4、抽象类的成员特点
抽象类的成员特点
成员变量
可以是变量,也可以是常量
构造方法
有构造方法,但是我们上一个程序中总结出抽象类不能实例化,那构造的意义是
什么呢?要想初始化子类,就必须先初始化父类,在继承的关系中有用
成员方法
可以有抽象方法 限定子类必须完成某些动作
也可以有非抽象方法 提高代码复用性
abstract class Animal5{
public int a;
public final int b = 20;
Animal5(){
a = 20;
System.out.println(a);
}
}
class Dog5 extends Animal5{
}
public class AbstractDemo2 {
public static void main(String[] args) {
Dog5 dog5 = new Dog5();
}
}
5、问题
一个类如果没有抽象方法,可不可以定义为抽象类?
可以
如果可以,有什么意义? 橙汁,水,牛奶等这些东西用共同的特点,我们把这些相同的行为概念归结成一个类 假设叫做液体。 至于后面有没有抽象方法,取决于这些东西有没有相同的行为,只是说有着相同的本质。没有 实际的共同的行为,也可不写抽象方法,也是合情合理的。 1、抽象类中可以没有抽象方法 2、抽象类不能被实例化
抽象类中可以存在哪些关键字?abstract关键不能和哪些关键字共存? private 不能共存 final 不能共存 static 不能共存 java中所有类都有一个共同的父类:Object
abstract class Liquid{
// //java中所有类都有一个共同的父类:Object
// Liquid(){
// super();
// }
//abstract关键字可以和public关键字共存
public abstract void show();
//abstract关键字和private关键字冲突
// private abstract void show1();
//非法的修饰符组合: abstract和final
// final abstract void show2();
//非法的修饰符组合: abstract和static
// static abstract void show3();
public static void show4(){
System.out.println("这是父类中的静态方法");
}
}
class Milk extends Liquid{
}
public class AbstarctSiKao {
public static void main(String[] args) {
//Liquid l = new Liquid(); //报错,抽象类不能被实例化
//Liquid l = new Milk();
Liquid.show4();
}
}
四、面向对象综合举例
/*
猫狗案例
具体事物:猫,狗
共性:姓名,年龄,吃饭
分析:从具体分析到抽象的过程
猫:Cat
成员变量:姓名,年龄
构造方法:无参构造,有参构造
成员方法:吃饭(猫吃鱼)
狗:Dog
成员变量:姓名,年龄
构造方法:无参构造,有参构造
成员方法:吃饭(狗吃肉)
通过分析我们发现,两个类存在相同的内容,所以提取出一个抽象类:Animal6
抽象动物类:
成员变量:姓名,年龄
构造方法:无参构造,有参构造
成员方法:吃饭(该方法是抽象的,没有具体的实现)
*/
具体实现:
//定义一个抽象动物类
abstract class Animal6 {
//姓名
private String name;
//年龄
private int age;
//无参构造
Animal6() {
}
//有参构造
Animal6(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;
}
//show方法,输出所有的成员变量值
public void show() {
System.out.println("姓名:" + this.name + ",年龄:" + this.age);
}
//吃饭的抽象方法
public abstract void eat();
}
class Dog6 extends Animal6 {
Dog6() {
}
Dog6(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
class Cat6 extends Animal6 {
Cat6() {
}
Cat6(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public class AbstractTest2 {
public static void main(String[] args) {
//使用多态创建第一个对象
Animal6 a = new Dog6("小白", 3);
a.show();
a.eat();
//创建第二个对象,使用公共的getXxx和setXxx进行赋值
Animal6 a2 = new Dog6();
a2.setName("大黄");
a2.setAge(4);
a2.show();
a2.eat();
//创建第三个对象
Animal6 a3 = new Cat6("小黑",2);
a3.show();
a3.eat();
}
}