面向对象3
十、抽象类
-
abstract可以用来修饰方法,也可以修饰类,如果修饰方法,那么该方法就是抽象方法,如果修饰类,那么就是抽象类
-
抽象类中可以没有抽象方法,但是有抽象方法一定要声明为抽象类
-
抽象类不能使用new关键字创建对象,它是用来让子类继承的
-
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的
-
子类继承抽象类,那么必须实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类
package com.oop.demo09; //abstract 抽象类,类,单继承,接口可以多继承 public abstract class Action { //abstract,抽象方法,只有方法名,没有方法的实现 public abstract void doSomething(); public void go(){ System.out.println("go"); } /* 1.不能new这个抽象类,只能靠子类去实现它:约束 2.抽象类中可以写普通的方法 3.抽象方法必须在抽象类中 4.抽象的抽象:约束 5.思考题: 不能new,存在构造器吗? 存在的意义? 抽象出来,提高开发效率 */ } package com.oop.demo09; public class A extends Action { @Override public void doSomething() { System.out.println("doSomething"); } }
-
定义抽象类:
-
抽象方法必须是public或者protect
-
抽象类不能实例化,依靠子类向上转型
-
抽象类必须有子类,使用extend继承,单继承
-
子类如果不是抽象类,必须重写抽象类中全部抽象方法
-
抽象类不能使用final关键字声明
-
-
抽象方法
-
只许声明,不包含方法体,不需要方法的具体实现
-
继承抽象类的子类必须重写父类的抽象方法
-
构造方法和类方法(static修饰的方法)不能声明为抽象方法
-
-
十一、接口
-
普通类:只有具体的实现
-
抽象类:具体实现和规范(抽象方法)都有
-
接口:只有规范,自己无法写方法,专业的约束,约束和现实分离,面向接口编程
-
接口就是规范,定义了一组规则,体现了世界中的“如果你是。。。你就必须能。。。”的思想。如果你是天使,则必须能飞,如果你是汽车,则必须能跑,如果你是好人,则必须干掉坏人;如果你是坏人,则必须欺负好人
-
接口的本质就是契约,就像我们人间的法律一样,制定好后大家遵守
-
OO的精髓,是对对象的抽象,最能体现这一点的是接口,为什么我们讨论设计模式,只针对具有抽象的语言(C++,java,c#等),就是因为设计模式研究的,实际上是如何合理的去抽象
-
-
声明类的关键字是class,声明接口的关键字是interface
-
public interface 接口名称 [extends 其他类名]{ [public][static][final] 数据类型 成员名称 = 常量值; [public][static][abstract] 返回值 抽象方法名(参数列表); }
-
实现接口
//class 类名称 implements 接口名称[,其他接口]{...}
-
11
package com.oop.demo10; //interfance 定义的关键字,接口都需要实现类 //抽象的思维,java架构师 public interface UserService { //常量 public static final int AGE =99; //接口中所实现的方法其实都是抽象的public abstract void add(String name); void delete(String name); void update(String name); void query(String name); } /* 作用: 1.约束 2.定义一些方法,让不同的人实现 3.public abstract 4.public static final 5.接口不能实例化,接口中没有构造方法 6.implement可以实现多个接口 7.必须重写接口中的方法 */ package com.oop.demo10; public interface TimeService { void timer(); } package com.oop.demo10; public class UserServiceImp1 implements UserService,TimeService { @Override public void add(String name) { } @Override public void delete(String name) { } @Override public void update(String name) { } @Override public void query(String name) { } @Override public void timer() { } }
-
接口和抽象类对比
-
相同点:
-
都可以被继承
-
都不能被直接实例化
-
都可以包含抽象方法
-
子类必须实现为实现的方法
-
-
不同点
-
接口支持多继承,抽象类单继承
-
一个类只能继承一个抽象类,但可以实现多个接口
-
接口的成员变量只能是public,static,final类型,抽象类的成员变量可以是任何类型
-
接口只能定义抽象方法,抽象类可以定义抽象方法和普通方法
-
接口中不含静态代码块以及静态方法,抽象类可以有
-
-
-
-
十二、内部类
-
内部类就是在一个类的内部定义一个类,比如,A类中定义一个B类,那么B类相对A类就是内部类,而A类相对B类就是外部类
-
//外部类名.内部类名 对象名 = new 外部类名().new 内部类名(); Outer.Inner inner = new Outer().new Inner();
-
-
-
成员内部类
-
//通过外部类来实例化内部类 //内部类 对象名 = 外部类对象.new 内部类(); Outer.Inner inner = outer.new Inner();
-
成员内部类可以直接访问外部类的所有数据,包括私有的
-
-
静态内部类
-
多一个关键字static,不需要依赖外部类
-
不能直接访问外部类的非静态成员,通过“new 外部类().成员”访问
-
-
局部内部类
-
区别于成员内部类,访问仅限于方法内或者该作用域内
-
不能有public,protect,private,和static修饰
-
-
匿名内部类
-
编写监听事件代码方便,容易维护
-
是唯一没有构造器的类,用于接口回调
-
//在主方法直接调用,不用实例化 //new 类名().方法名(); new Apple().eat();
-
package com.oop.demo11; public class Outer { private int id=10; public void out(){ System.out.println("这是外部类的方法"); } public class Inner{ public void in(){ System.out.println("这是内部类的方法"); } //获得外部类的私有属性,方法等 public void getID(){ System.out.println(id); } } } //一个java类中可以有多个class类,单只能有一个public class //局部内部类 class A{ } package com.oop.demo11; public class Test { public static void main(String[] args) { //没有名字初始化类,不用将实例化保存到变量中 //隐藏内部类 new Apple().eat(); UserService userService = new UserService() { @Override public void hello() { } }; } } class Apple{ public void eat(){ System.out.println("1"); } } interface UserService{ void hello(); } package com.oop; import com.oop.demo06.A; import com.oop.demo06.B; import com.oop.demo07.Person; import com.oop.demo07.Student; import com.oop.demo07.Teacher; import com.oop.demo11.Outer; public class Application { public static void main(String[] args) { /* Person person =new Person(); Student student = new Student(); student.test("斌"); student.test1(); */ /* //方法的调用只和左边,定义的数据类型有关 A a = new A(); a.test(); //父类的引用指向子类 B b = new A(); b.test(); */ /* //一个对象的实际类型是确定的 //new Student //new Person //可以指向的引用类型就不确定了,父类的引用指向子类 //Student 能调用的方法都是自己的或者继承父亲的 Student s1 = new Student(); //Person,父亲类,可以指向子类,但是不能调用子类独有的方法 Person s2 = new Student(); Object s3 = new Student(); //对象能执行哪些方法,主要看对象左边的类型,和右边关系不大 s2.run(); s1.run(); ((Student)s2).eat();//子类重写了父类的方法,执行子类的方法 s1.eat(); */ /* Object object = new Student(); System.out.println(object instanceof Student);//true System.out.println(object instanceof Person);//true System.out.println(object instanceof Object);//true System.out.println(object instanceof Teacher);//false System.out.println(object instanceof String);//false System.out.println("==========="); Person person = new Student(); System.out.println(person instanceof Student);//true System.out.println(person instanceof Person);//true System.out.println(person instanceof Object);//true System.out.println(person instanceof Teacher);//false //System.out.println(person instanceof String);//编译错误 System.out.println("==========="); Student student = new Student(); System.out.println(student instanceof Student);//true System.out.println(student instanceof Person);//true System.out.println(student instanceof Object);//true //System.out.println(student instanceof Teacher);//编译错误 //System.out.println(student instanceof String);//编译错误 */ Outer outer = new Outer(); //通过外部类来实例化内部类 Outer.Inner inner = outer.new Inner(); inner.in(); inner.getID(); } } /* 1.父类引用指向子类的对象 2.把子类转换为父类,向上转型 3.把父类转换为子类,向下转型;强制转换 4.方便方法的调用,减少重复的代码 */
-