黑马程序员_Java多态和内部类

多态

定义:

    某一类事物的多种存在形态。

    例:动物中猫,狗。

    猫这个对象对应的类型是猫类型

    猫 x = new()

    同时猫也是动物中的一种,也可以把猫称之为动物。

    动物 y = new();

    动物是猫和狗具体事物中抽取出来的父类型。

    父类型引用指向了子类对象。

abstract class Animal
{
	public abstract void eat();
}

class Cat extends Animal
{
	public void eat()
	{
		System.out.println(“吃鱼”);
	}
	public void catchMouse()
	{
		System.out.println("抓老鼠");
	}
}

class Dog extends Animal
{
	public void eat()
	{
		System.out.println("吃骨头");
	}
	public void kanJia()
	{
		System.out.println("看家");
	}
}


class DuoTaiDemo 
{
	public static void main(String[] args) 
	{
		//Cat c = new Cat();
		//Dog d = new Dog();
		Animal c = new Cat();//类型提升。向上转型。
		function(c);
		//如果想要调用猫的特有方法,如何操作?
		//强制将父类的引用转成子类类型。
		//千万不要出现这样的操作:将父类对象转成子类类型。
		//我们能转换的是父类引用指向了自己子类对象时,改引用可以被提升,也可以被强制转换。
		//多态自始至终都是子类对象在做着变化。
		Cat a = (Cat)c;
		c.catchMouse();
		Animal d = new Dog();
		function(d);
	}
	public static void function(Animal a)
	{
		a.eat();
	}
}

1.多态的体现

    父类的引用指向了自己的子类对象。

    父类的引用也可以接收自己的子类对象。

2.多态的前提

    必须是类与类之间有关系,要么继承要么实现。

3.多态的好处

    多态的出现大大的提高了程序的扩展性。

4.多态的弊端

    提高了扩展性,但是只能使用父类的引用访问父类中的成员。

5.多态的应用

/*
基础班学生:
	学习,睡觉。
高级班学生:
	学习,睡觉。

可以将这两类事物进行抽取
*/

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.pringtln("base study");
	}
	public void sleep()
	{
		System.out.println("坐着睡");
	}
}

class AdvStudent extends Student
{
	public void study()
	{
		System.out.pringtln("adv study");
	}
}



class  DuoTaiDemo3
{
	public static void main(String[] args) 
	{
		DoStudent ds = new DoStudent();
		ds.doSome(new BaseStudent);
		ds.doSome(new AdvStudent);
		/*BaseStudent bs = new BaseStudent();
		bs.study();
		bs.sleep();
		AdvStudent as = new AdvStudent();
		as.study();
		as.sleep();
		*/
	}
	
}

6.多态的出现代码中的特点(多态使用的注意事项)

    在多态中成员函数的特点:

        在编译时期:参阅引用类型变量所属的类中是否有调用的方法,如果有,编译通过,如                 果没有编译失败。

        在运行时期:参阅对象所属的类中是否有调用方法。

        简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。

    成员变量的特点:无论编译和运行,都参考左边(引用型变量所属的类)

    在多态中,静态成员函数的特点:无论编译和运行,都参考左边。

 

class Fu
{
	int num = 5;
	void method1()
	{
		System.out.println("fu method_1");
	}
	coid method2()
	{
		System.out.println("fu method_2");
	}
}

class Zi extends Fu
{
	int num = 8;
	void method1()
	{
		System.out.println("Zi method_1");
	}
	void method3()
	{
		System.out.println("Zi method_3");
	}
}

class  DuoTaiDemo4
{
	public static void main(String[] args) 
	{
		Fu f = new Zi();
		System.out.println(f.num);
		f.method1();
		f.method2();
		//f.method3();
/*
在多态中成员函数(非静态)的特点:
在编译时期:参阅引用类型变量所属的类中是否有调用的方法,如果有,编译通过,如果没有编译失败。
在运行时期:参阅对象所属的类中是否有调用方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
			  成员变量的特点:无论编译和运行,都参考左边(引用型变量所属的类)。
在多态中,静态成员函数的特点:无论编译和运行,都参考左边。

*/


		Zi z = new Zi();
		z.method1();
		z.method2();
		z.method3();
	}
}


练习:多态的主板展示:

/*
需求:
电脑运行实利
电脑运行基于主板
*/

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.pringln("netcard open");
	}
	public void clse()
	{
		System.out.println("netcard close");
	}
}

class DuoTaiDemo5  //主函数
{
	public static void main(String[] args) 
	{
		MainBoard mb = new MainBoard();
		mb.run();
		mb.usePCI(null);
		mb.usePCI(new NetCard());
		
	}
}

 

练习:多态的扩展事例:

/*
需求:数据库的操作。
数据是:用户信息。

1.连接数据库。JDBC  Hibernate
2.操作数据库。
	c create r read u update d delete
3.关闭数据库连接。
*/

interface UserInfoDao
{
	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  DuoTaiDemo6
{
	public static void main(String[] args) 
	{
		//UserInfoByJDBC ui = new UserInfoByJDBC();
		UserInfoDao ui =  new UserInfoByJDBC()
		ui.add(user);
		ui.delete(user);
	}
}

Object--equals()方法:

/*
object:是所有对象的直接或者间接父类,传说中的上帝。
该类中定义的肯定是所有对象都具备的功能。

Object类中已经提供了对对象是否相同的比较方法。
如果自定义类中也有比较相同的功能,没有必要重新定义。
只要沿袭父类中的功能,建立自己特有的比较内容即可,这就是覆盖。
*/

class Demo //extends Object
{
	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 compare(Demo d)
	{
		return this.num==d.num;
	}
	*/
}

class  ObjectDemo
{
	public static void main(String[] args) 
	{
		Demo di = new Demo(4);
		Demo d2 = new Demo(5);
		System.out.println(d1.equals(d2));


	}
}


内部类

内部类:

    就是将一个类定义在另一个类的里面,对里面那个类就称之为内部类(内置类,嵌套类)。

访问特点:

    内部类可以直接访问外部类中的成员,包括私有成员。

    而外部类要访问内部类中的成员必须要建立内部类的对象。

访问格式:

    1.当内部类定义在外部类的成员位置上,而且非私有,可以在外部其它类中直接建立内部类对象。

        格式:外部类名.内部类名 变量名 外部类对象.内部类对象;

        Outer.Inner in = new Outer().new Inner();

    2.当内部类在成员位置上,就可以被成员修饰符修饰。

        比如,private:将内部类在外部类中进行封装。

        static:内部类就具备了static的特性。

    当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限。

    在外部类中,如何直接访问静态内部类中的非静态成员呢?

        new Outer.Inner().function();

    在外部类中,如何直接访问静态内部类中的静态成员呢?

        Outer.Inner.function();

 

    注意:当内部类中定义了静态成员,该内部类必须是静态的。

    当外部类中的静态方法访问内部类时,内部类也必须是静态的。

 

    当描述事物时,事物的内部还有事物,该事物用内部类来描述。

    因为内部类事物在使用外部事物的内容。

class Outer
{
	private static int x = 3;
	static class Inner   //静态内部类。
	{
		int x = 4;
		void function()
		{
			int x = 6;
			System.out.println("inner:"+Outer.this.x);//内部类能直接访问外部类原因:省略了Outer.this.
		}
	}
	void method()
	{
		Inner in = new Inner();
		in.function();
	}
}




class InnerClassDemo 
{
	public static void main(String[] args) 
	{
		Outer out = new Outer();
		out.method();
		//直接访问内部类中的成员。
		Outer.Inner in = new Outer().new Inner();
		in.function();
		new Outer.Inner().function();
	}
}

内部类定义在局部时

    1.不可以被成员修饰符修饰

    2.可以直接访问外部类中的成员,因为还持有外部类中的引用。

    但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。

class Outer
{
	int x = 3;
	void method()
	{
		class Inner
		{
			final int y = 4;
			void function()
			{
				System.out.println(Outer.this.x);
			}
		}
		new Inner().function;
	}
}

class  InnerClassDemo2
{
	public static void main(String[] args) 
	{
		new Outer().method();
	}
}

匿名内部类:

匿名内部类:

    1.匿名内部类其实就是内部类的简写格式。

    2.定义匿名内部类的前提:

        内部类必须是继承一个类或者实现接口。

    3.匿名内部类的格式:new 父类或者接口(){定义子类的内容}

    4.其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象。

    5.匿名内部类中定义的方法最好不要超过3个。

abstract class AbsDemo
{
	abstract void show();
}

class Outer
{
	int x = 3;
	/*
	class Inner extends AbsDemo
	{
		void show()
		{
			System.out.println("show:"+x);
		}
	}
	*/
	public void function()
	{
	   //	new Inner().show();
		AbsDemo d = new AbsDemo() //多态。
	    {
			   void show()
			   {
			   System.out.println("x="+x);
			   }
	    }
		d.show();
		
	}

}

class InnerClassDemo3 
{
	public static void main(String[] args) 
	{
		new Outer().function();
	}
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值