黑马程序员-面向对象(抽象类、接口与内部类)

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------  

 

 

抽象类

当描述一个事物的时候,如果不能确定功能函数如何定义,那么该类就可以定义为抽象类,功能函数应该描述为抽象函数。

抽象类的格式:

Abstract class Demo{

      成员属性;

      非抽象方法(){};

      abstract抽象方法;

}

 

抽象的优点

1:提高代码复用性

2:强制子类实现父类中没有实现的功能

3:提高代码的扩展性,便于后期的代码维护

 

抽象方法存在于抽象类和接口类,有抽象方法的不一定是抽象类,也可以是接口类。

问题:抽象类可以没有抽象方法吗?

答:抽象类也可以没有抽象方法,但是这样的抽象类无实际使用意义,除非是想要一个类不能被直接实例化,则可以定义为无抽象方法的抽象类

 

抽象类需要注意的地方

(1)抽象类和抽象方法必须被abstract修饰

(2)抽象类中的抽象方法必须被子类实现

(3)抽象类可以同时存在抽象方法和非抽象方法

(4)抽象类可以实现(implements)接口,抽象类可继承实体类,但前提是实体类的构造函数不能被私有化

(5)非抽象类在继承抽象类的时候,必须要把所有的抽象方法实现

(6)抽象类继承抽象类的时候,可以不用实现父类的抽象方法

(7)抽象方法不能用private关键字修饰,因为抽象方法是必须要被继承的,如果被私有修饰,那么将对子类不可见

(8)抽象方法也不能static修饰,因为用static修饰的方法可以用类名调用,但是抽象方法是没有被实现的,会出错,所以…

(9)抽象方法不能用final修饰,因为被final修饰的不能被继承,而抽象方法是必须要被继承的

(10)抽象类可以有构造方法,也可以不写构造方法,抽象类虽然不能创建对象,但构造方法是有意义的,可以为子类初始化对象,简化代码

 

接口:

接口的使用格式:

interface 接口名
{
属性
抽象方法
}


 

接口的作用(红色为主要作用)

程序的解耦

提供了标准和规范

弥补了类的单继承限制

扩展了功能

 

接口需要注意的地方:

(1)interface接口的成员属性全是静态常量,默认的修饰符为public Static final,如果没有写,编译的时候,编译器自动加上,一般不定义静态常量

(2)接口中的成员方法全部是抽象方法,默认修饰符为public abstract,如果没有写上,编译器自动加上

(3)接口不可以存在构造函数,不能创建对象

(4)在实现接口的时候,要把接口中的所有抽象方法覆写

(5)接口中不允许存在非抽象的方法(这和抽象类有区别),因为在编译时期,编译器会给所有的方法统一加上默认的修饰符public abstract

 

接口的多实现

前面说到java不支持多继承,但是接口支持多实现,这个就是对不支持多继承的一个补偿

那这个的原因是什么呢

因为继承有方法体,如果允许继承多继承,如果有继承的多个类中有同名的方法,那么可能就会产生冲突

但是接口就有一点区别,却别就是在于接口里面的方法没有方法体,即使有同名的方法,也不影响,只能在覆写的时候,由使用者自定义实现内容

 

内部类

内部类的使用格式

格式:

外部类名.内部类名  变量名 =外部类对象.内部类对象;

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

例子:

class Outer
{
   	private int x = 3;
   	class Inner//定义在外部类成员位置上的内部类
   	{
      		int x = 4;
      		void function()
      		{
         		int x = 6;
         		System.out.println("innner :"+Outer.this.x);
      		}
   	}
   	void method()
   	{
      		Inner in = new Inner();
      		in.function();
   	}
}

class  InnerClassDemo
{
   	public static void main(String[] args) 
   	{
      		Outer.Inner in = new Outer().new Inner();
      		in.function ();
   	}
}

内部类的访问规则:

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

   之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this

2外部类要访问内部类,必须建立内部类对象

问题1:类能不能被私有修饰

答:是可以的,因为内部类可以被私有修饰,当内部类处于外部类的成员位置的时候,可以私有修饰

但是外部类是不允许被私有修饰的

在这要注意Static修饰,修饰了内部类之后,如果内部调用的方法没有被静态修饰的话,不能被类名直接调用

回顾了一下

static 的使用规则

1static修饰属性,如static int num;那么这个num就是属于全局属性,所有对象共享的,可以被直接类名调用,Person p1 = newPerson();既可以p1.num = 10;也可以Person.num = 10;这样调用

 

2static修饰方法,

int num;

public static fun(int inf)

{

this.num = inf;

}

这样是错误的,因为static修饰的方法只能调用static修饰的属性,而num没有被static修饰

其实我这之前有一个误区,一直学到内部类才察觉到,就是以为static修饰的方法,是修饰了一整个方法体,连带方法体里面的属性也被static给修饰了,其实不完全是,static只是修饰了方法名,此时方法可以通过类名调用,我过去是在于以为方法内部的属性同样必须要经过static修饰或者已经在方法外部定义为static,这个方法才能编译成功。正确的说法,所谓调用,是外部定义的。被static修饰的方法,去使用外部的属性,这叫调用,在方法体里面定义的属性,属于局部的变量,则不属于调用,所以,不需要经过static修饰,直接可用,如果外部想用该属性,必须经过内部类的类名调用,也不能直接用,因为它不属于全局属性,属于局部变量

 

3static修饰类,其实应该也就是指内部类

基于java的面向对象思想,其实可以这样想,只要把内部类看成是一个成员方法或者成员变量即可,那么使用规则如出一辙,区分好调用了内部类中自己定义的方法和属性即可。

注意:内部类的成员变量和成员函数不能单独声明为静态,只有把内部类声明为static,这个内部类才能被静态声明的方法和属性,否则编译会报错,某些内部类不能被static修饰,下面说到

 

内部类定义在局部时的注意事项:

1内部一般只出现在外部类的成员位置上,在这个位置上,可以被static修饰,但是也有例外,就是出现在外部类的方法里面,再定义一个内部类,这个内部类就不是出现在外部类的成员位置上了,而是出现在外部类成员位置的内部位置,这是局部位置,出现在这个位置的内部类,不可以被static修饰,也即是说,只有在外部类成员位置上的内部类才能被static修饰,局部内部类不能被static修饰

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

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

class Outer
{
	int x = 3;
	void method(final int a)
	{
		final int y = 4;  //内部类要访问这个变量,必须用finally修饰
		class Inner   // 此时内部类定义在局部位置
		{
			void function()
			{
				System.out.println(y);
			}
		}
		new Inner().function();
	}
}


 

匿名内部类:

匿名内部类的格式

new 接口或者抽象类()

{

  覆写抽象方法

}

示例:

class Inner extends AbsDemo
{
	int num = 90;
	void show();
	{
		System.out.println("show :"+num);
	}
}
可以写成内部类形式
new AbsDemo
{
	int num = 90;
	void show()
	{
		System.out.println("show :"+num);
	}
}.show();//红色部分是一个对象


 

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

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

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

问题:那怎么知道到底是继承还是实现呢?

答:使用者自己知道

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

4,其实匿名内部类就是一个匿名子类对象。可以理解为带内容的对象。

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

 

匿名内部类的实践

class Test
{
	static Inter function()//返回值为Inter的一个方法
	{
		return new Inter()
		{
			void method();
		}            //红色部分是一个Inter类型的匿名内部类
		//匿名内部类的格式:  new 父类或者接口(){定义子类的内容}
	}
	class Demo interface Inter//此时接口是Inter,内部类名为Demo
	{
		void method();
	}
}
public class InnerTest
{
	public static void main(String args[])
	{
		Test.function().method();
	}
}

上述代码中,Test.function().method();可以分解成三部分

Test.function():Test类中有一个静态的方法function,因为通过类名调用

.method():function这个方法运算后的结果是一个对象。

而且是一个Inter类型的对象。

因为只有是Inter类型的对象,才可以调用method方法。

 

问题:为什么成员内部类不能有静态属性呢

首先明确内部类有四种

1)成员内部类

2)局部内部类

3)静态内部类

4)匿名内部类

答:这里说的是成员内部类,那么就排除了处于成员位置上的静态内部类,其实说的就是内部类的方法和属性不能单独设置为静态,要设置,可以,必须把内部类变成静态内部类,一起设置

建立内部类对象时应注意
在外部类的内部可以直接使用inner s=new inner();(因为外部类知道inner是哪个类,所以可以生成对象。)
而在外部类的外部,要生成(new)一个非静态的内部类对象,需要首先创建一个外部类对象(外部类可用),然后在生成一个内部类对象。
Outer.Inner in=new Outer.new.Inner()

注意:生成(new)一个静态内部类不需要外部类成员:这是静态内部类和成员内部类的区别。静态内部类的对象可以直接生成:
Outer.Inner in=new Outer.Inner()
//这个是静态内部类的创建方式,静态内部类必须要这样声明
而不需要通过生成外部类对象来生成。这样实际上使静态内部类成为了一个顶级类


 

 

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

详细请查看:http://edu.youkuaiyun.com 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值