Day08 面向对象
——多态、Object类
4.9 多态
定义:某一类事物的多种存在形态
例:动物中猫、狗。
猫这个对象对应的类型是猫类型。 猫 x = new 猫();
同时猫也是动物中的一种,也可以把猫成为动物。
动物 y = new 猫();
动物是猫和狗具体事务中抽取出来的父类型。
父类型引用指向了子类对象。
1.多态的体现 父类的引用指向了自己的子类对象。父类的引用也可以接收自己的引用对象。
2.多态的前提 必须是类与类之间有关系,要么继承,要么实现,存在覆盖。
3.多态的好处 多态的出现,大大提高了程序的扩展性。扩展性:前期预先调用功能,后期定义子类去实现功能,把子类作为参数传递进来实现后期扩展性。
4.多态的弊端 提高了扩展性,但是只能使用父类中的引用访问父类中的成员。
5.多态的应用
6.多态中成员函数的特点(多态使用的注意事项)
动物:猫、狗
abstract class Animal
{
public abstract void eat();//吃这个不确定,使用抽象
}
class Cat extends Animal
{
public void eat()
{
System.out.println("eat fish");
}
public void catchMouse()
{
System.out.println("catch Mouse");
}
}
class Dog extends Animal
{
public void eat()
{
System.out.println("eat meat");
}
public void bark()
{
System.out.println("bark");
}
}
class Pig extends Animal
{
public void eat()
{
System.out.print("eat siliao");
}
public void sleep()
{
System.out.println("sleep");
}
}
class duotai
{
public static void main(String[] args)
{
//Cat c = new Cat();
//c.eat();
//Dog d = new Dog();
//d.eat();
//Cat c = new Cat();
//c.eat();
//Cat c1 = new Cat();
//c1.eat();
//Cat c = new Cat();
/*
Cat c1 = new Cat();
function(c1);
function(new Dog());
function(new Pig());
*/
//Animal c = new Cat();
//c.eat();
function(new Cat());
function(new Dog());
function(new Pig());
}
public static void function(Animal a)//Animal a = new Cat();
{
a.eat();
}
/*
public static void function(Cat c)
//本类类型接收本类对象,Cat c = new Cat();
{
c.eat();;
}
public static void function(Dog d)//function不用改,重载
{
d.eat();;
}
public static void function(Pig p)
{
p.eat();;
}
*/
}
转型
abstract class Animal
{
public abstract void eat();//吃这个不确定,使用抽象
}
class Cat extends Animal
{
public void eat()
{
System.out.println("eat fish");
}
public void catchMouse()
{
System.out.println("catch Mouse");
}
}
class Dog extends Animal
{
public void eat()
{
System.out.println("eat meat");
}
public void bark()
{
System.out.println("bark");
}
}
class Pig extends Animal
{
public void eat()
{
System.out.print("eat siliao");
}
public void sleep()
{
System.out.println("sleep");
}
}
class duotai
{
public static void main(String[] args)
{
//Animal a = new Cat();//类型提升,向上转型
//a.eat();
//如果想要调用猫的特有方法时,如何操作
//强制将父类的引用转成子类类型,向下转型。
//Cat c = (Cat)a;
//c.catchMouse();
//这种写法不允许,将父类对象转成子类类型
//我们能转换的是父类应用指向了自己的子类对象时,该应用可以被提升,也可以被强制转换。
//多态自始至终都是子类对象在做着变化。
//Animal a = new Animal();
//Cat c = (Cat)a;
function(new Dog());
function(new Cat());
}
public static void function(Animal a)//Animal a = new Cat();
{
a.eat();
/*
if(a instanceof Animal)//不要把父类型的判断放在前面
{
System.out.println("haha");
}
else
*/
if (a instanceof Cat)
{
Cat c = (Cat)a;
c.catchMouse();
}
else if (a instanceof Dog)
{
Dog c= (Dog)a;
c.bark();
}
}
}
多态示例
多态将对象调用这件事变简化,以前指挥每一个对象做事情,现在是可以指挥一批对象做事情,因为找到这些对象的共同所属类型。把对象不断向上抽象,总能找到共同点,可以统一操作很多对象。
基础班学生:学习、睡觉
高级版同学:学习、睡觉
abstract class Student
{
public abstract void study();
public void sleep()
{
System.out.println("躺着睡");
}
}
class DoStudent
{
public void doSome(Student stu)
{
stu.study();
stu.sleep();
}
}
class BaseStudent extends Student
{
public void study()
{
System.out.println("base study");
}
public void sleep()
{
System.out.println("坐着睡");//覆写
}
}
class AdvStudent extends Student
{
public void study()
{
System.out.println("adv study");
}
}
class duotai1
{
public static void main(String[] args)
{
/*
BaseStudent bs = new BaseStudent();
bs.study();
bs.sleep();
AdvStudent as = new AdvStudent();
as.study();
as.sleep();
*/
DoStudent ds = new DoStudent();
ds.doSome(new BaseStudent());
ds.doSome(new AdvStudent());
}
}
多态中成员函数的特点(非静态,只有非静态才有重写的特性)
多态中:父类有指向子类对象的时候,由本类指向本类对象不是多态
Fu f = new zi();
在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有,编译失败。
在编译时,看的是f这个引用型变量所属类Fu里是不是有调用的方法:
f.method1();–>有
f.method2();–>有
f.method3();–>没有,编译失败
在运行时期:参阅对象所属的类中是否有调用的方法。
在运行时,看的是new Zi()这个对象所属类:Zi,Zi中有没有method1,method2,有就运行自己的,没有就找父类中的。
总结:成员函数在多态调用时,编译看左边,运行看右边。
面试:
1.在多态中,静态成员函数的特点:无论编译和运行,都参考左边。
2.在多态中,成员变量的特点:无论编译和运行,都参考左边(引用型变量所属的类)。
父类和子类,有相同名称的成员变量,这两个变量也是静态的,多态时,打印结果:父类。
静态绑定的是静态绑定,非静态绑定的是动态绑定。
class Fu
{
static int num = 5;
void method1()
{
System.out.println("fu method_1");
}
void method2()
{
System.out.println("fu method_2");
}
static void method4()
{
System.out.println("fu method_4");
}
}
class Zi extends Fu
{
static int num = 8;
void method1()
{
System.out.println("zi method_1");
}
void method3()
{
System.out.println("zi method_3");
}
static void method4()
{
System.out.println("zi method_4");
}
}
class duotai3
{
public static void main(String[] args)
{
Fu f = new Zi();
//f.method4();
System.out,println(f.num);//静态只看引用所属,那个类 5
//静态覆盖静态,结果 fu method_4,只有非静态才有重写功能
Zi z = new Zi();
z.method4();//结果 zi method_4
//Fu f = new Zi();
//System.out.println(f.num);//-->5
//Zi z = new Zi();
//System.out.println(z.num);//-->8
//在多态中,成员变量的特点:无论编译和运行,都参考左边(引用型变量所属的类)。
//Fu f = new Zi();
//f.method1();
//f.method2();
//f.method3();
/*
Zi z = new Zi();
z.method1();
z.method2();
z.method3();
--> zi method_1//子类中把父类覆盖
fu method_2//子类继承
zi method_3//子类特有
*/
}
}
多态的主板示例
需求:电脑运行实例。电脑运行基于主板。
/*
class MainBoard
{
public void run()
{
System.out.println("mainboard run");
}
public void useNetCard(NetCard c)
{
c.open();
c.close();
}
}
class NetCard
{
public void open()
{
System.out.println("netcard open");
}
public void close()
{
System.out.println("netcard close");
}
}
*/
interface PCI
{
public void open();
public void close();
}
class MainBoard
{
public void run()
{
System.out.println("mainboard run");
}
public void usePCI(PCI p)//PCI p = new NetCard();接口型引用指向自己的子类对象
{
if(p != null)
{
p.open();
p.close();
}
}
}
class NetCard implements PCI
{
public void open()
{
System.out.println("netcard open");
}
public void close()
{
System.out.println("netcard close");
}
}
class SoundCard implements PCI
{
public void open()
{
System.out.println("SoundCard open");
}
public void close()
{
System.out.println("SoundCard close");
}
}
class duotai4
{
public static void main(String[] args)
{
MainBoard mb = new MainBoard();
mb.run();
mb.usePCI(null);
mb.usePCI(new NetCard());
mb.usePCI(new SoundCard());
}
}
多态的扩展示例
需求:数据库操作。
1.连接数据库。JDBC Hibernate 2.操作数据库。 c create r read u update d delete 3.关闭数据库
interface UserInfoDao//data access object
{
public void add(User user);
public void delete(User user);
}
class UserInfoByJDBC implements UserInfoDao
{
public void add(User user)
{
1.JDBC连接数据库
2.使用sql添加语句添加数据库
3.关闭连接
}
public void delete(User user)
{
1.JDBC连接数据库
2.使用sql删除语句删除数据库
3.关闭连接
}
}
class UserInfoByHibernate implements UserInfoDao
{
public void add(User user)
{
1.Hibernate连接数据库
2.使用sql添加语句添加数据库
3.关闭连接
}
public void delete(User user)
{
1.Hibernate连接数据库
2.使用sql删除语句删除数据库
3.关闭连接
}
class DBOperate
{
public static void main(String[] args)
{
//UserInfoByJDBC ui = new UserInfoByJDBC();
//UserInfoByHibernate ui = new UserInfoByHibernate();
UserInfoDao ui = new UserInfoByJDBC();
ui.add(user);
ui.delete(user);
}
}
Object类——equals()
equals(Object obj) 指示其他某个对象是狗与此对象“相等”。
Object:是所有对象的直接或者间接父类,传说中的上帝。该类中定义的肯定是多有对象都具备的功能。
Object类中已经提供了对对象是否相同的比较方法。如果自定义类中有比较相同的功能,没有必要重新定义。只要沿袭父类中的功能,建立自己特有比较的内容即可。这就是覆盖。
class Demo//extends Object
{
/*
Demo()
{
super();
}
*/
private int num;
Demo(int num)
{
this.num = num;
}
public boolean equals (Object obj)//复写,覆盖
//Object obj = new Demo();
//多态,父类指向子类对象,当想使用子类中特有内容,向下转型
{
if(!(obj instanceof Demo))//判断
return false;
Demo d = (Demo)obj;//转换
return this.num == d.num;
}
//public boolean equals (Demo d)//重载,参数类型不同
/*
public boolean compare(Demo d)
{
return.this.num == d.num;
}
*/
public String toString()
{
return "demo:" + num;//-->demo:4
}
}
class ObjectDemo
{
public static void main(String[] args)
{
/*
Demo d1 = new Demo();
Demo d2 = new Demo();
Demo d3 = d1;
//equals 指示其他某个对象是否与此对象“相等”
System.out.println(d1.equals(d2));//-->false,null时比较的地址值
System.out.println(d1.equals(d3));//-->true
System.out.println(d1 == d2);//-->false
System.out.println(d1 == d3);//-->true
*/
Demo d1 = new Demo(4);
Demo d2 = new Demo(6);
System.out.println(d1.equals(d2));
//System.out.println(d1.compare(d2));
System.out.println(d1.toString());
}
}
Object类——toString()
toString() 返回该对象的字符串表示。= getClass().getName() + ‘@’ + IntegertoHexString(hashCode())
Demo d1 = new Demo(4);
System.out.println(d1.toString());
–>Demo@15db9742
Demo:对象所属类; @右边:对象的内存地址 hashCode