疯狂java学习笔记之面向对象(九) - 抽象和接口
一、抽象(abstract):
1、抽象类:
使用abstract修饰的类就是抽象类;
相比于普通类抽象类增加了支持抽象方法的功能,但也丢失了创建实例的功能(抽象类中不能创建实例),其他普通类有的抽象类可以有。
抽象类的三个注意点:
①、虽然抽象类不能创建实例,但它依然有构造器(主要给其子类的构造器调用-子类至少调用父类构造器一次);
②、抽象类中可以没有抽象方法(可有可无);
③、抽象类总是不能创建实例/对象的 - 即使它没有包含抽象方法。
public abstract class TestAbstract{
private int age; {
System.out.println("-这是个对象初始化块-");
} public TestAbstract(){} //虽然抽象类不能创建实例,但它依然有构造器(主要是供其子类构造器调用,至少调用一次)
//子类不使用super()时则隐式调用父类无参构造器,有super()则根据参数来决定。
public TestAbstract(int age){
this.age = age;
} public static void main(String[] args){
System.out.println("Hello World!!");
//抽象类中不能创建实例,编译时即报错
//TestAbstract ta = new TestAbstract();
}
}
2、抽象方法:
使用abstract修饰且没有方法体的方法就是抽象方法。
注意点:
①、抽象方法不能有方法体 - 花括号内容(出现花括号没任何代码都算有方法体);
②、abstract不能和final同时出现 - 因为abstract方法必须由子类去重写,而final修饰的方法又不允许重写,因此不能同时出现;
对于abstract类来说,该类主要用于派生子类,final修饰的类同样不允许被集成,因此也不能同时出现 - abstract和final是永远互斥的;
③、abstract与static不能同时修饰方法 - static修饰的方法编译时已经确定下来,无法让子类@Override;
④、abstract与private不能同时修饰方法 - private修饰的方法不能被子类访问,而abstract又要求方法必须由子类重写,所以两者是互斥的。
public abstract class TestAbstract2{
//抽象类相对于普通类除了不能创建实例,其他功能都是有的,普通方法等能存在。
public void info(){} //抽象方法中不能有方法体-即使方法体内容为空
//public abstract void aa(){} public abstract void test(); //abstract 与static不能同时修饰方法 - static修饰的方法编译时已经确定下来,无法让子类@Override
//public abstract static void bb(); //abstract方法必须由子类重写,而private又不能让子类访问所以出错
private abstract void cc(); }
三、抽象的作用:
抽象类的作用:主要是与"模版模式" 结合一起使用的。
比如有如下场景需求:程序要实现A方法,但A方法又需要调用B方法且B方法在该类中暂时不知道如何实现(因为其子类实现B方法的方法可能都不一样,因此B方法可定义成抽象方法)。
抽象类的子类一般要实现抽象父类提供的所有方法,否则该子类也只能是抽象类(这样就无实际意义~)
abstract class SpeedMeter{
//定义一个转动速度。
private double turnRate; //抽象类的构造器主要用于被子类的构造器调用
public SpeedMeter(double turnRate){
this.turnRate = turnRate;
} //对于private修饰的Field一般推荐设置个set和get方法,典型的封装
public void setTurnRate(double turnRate){
this.turnRate = turnRate;
} public double getTurnRate(){
return this.turnRate;
} //计算速度的方法
/*
这里就是模版模式,此处我们定义一个计算速度的模板:转速*周长
但此处并不清楚计算周长方法,所以此处把周长getSpeed()定义成抽象方法,子类只需提供计算周长的方法即可
计算周长的方法是有差异的,车轮:2*PI*半径等
*/
public abstract double getSpeed(); } class CarSpeedMeter extends SpeedMeter{
private double radius; public CarSpeedMeter(double radius,double turnRate){
super(turnRate);
this.radius = radius;
} @Override
public double getSpeed(){
return 2 * radius * Math.PI;
}
} class TankSpeedMeter extends SpeedMeter{
private double bianchang;
public TankSpeedMeter(double bianchang,double turnRate){
super(turnRate);
this.bianchang = bianchang;
} //假设坦克的周长计算方法为 8 * 边长
@Override
public double getSpeed(){
return 8 * bianchang;
}
} public class TestSpeedMeter{
public static void main(String[] args){
SpeedMeter sm = new CarSpeedMeter(20,2000);
System.out.println("汽车的速度为: " + sm.getSpeed());
SpeedMeter tk = new TankSpeedMeter(8,1000);
System.out.println("坦克的速度为: " + tk.getSpeed());
}
}
二、接口(interface):
接口的作用非常丰富,接口往往是和设计模式结合一起使用的。
接口可以认为是一种"彻底"的抽象类,它是从多个相似的类中抽取出来的一种规范,接口体现的是规范。
接口体现的规范:如主板上各种不同类型的"插槽",无论接入的哪个厂商、型号的硬件都可以彼此进行通信(任何一套公开的标准/规范,需要通过接口来体现)。
接口定义语法:
[修饰符] interface 接口名{
//0~N 个Field、特殊的Field
//0~N 个抽象方法
//0~N 个内部类、内部接口、内部枚举类定义
}
[修饰符]:只能是public和默认省略,不能是protected因为接口在保外,而protected只能在包名进行访问
接口名: 由多个单词连缀而成,每个单词的首字母要大写,推荐以i开头(c#定义已i开头且是个不错的习惯)。
注意点:
①、接口不能有构造器,也不能有初始化块;
②、接口的Field默认有3个修饰符: public static final,无论你写或不写,反正都有这三个修饰符;
接口的Field定义时必须指定初始值 -- 接口Field默认有static final修饰,final修饰的变量只能被赋值一次,你不指定系统给你赋默认值0、0.0、null等。
③、接口的方法默认有2个修饰符:public abstract,无论你写与不写,反正都有这二个修饰符;
接口的方法不能有static,因为接口的方法默认有abstract修饰。
④、接口的内部类、内部枚举类、内部接口,默认有两个修饰符: public static
public interface iWalk{
int age = 33;
//接口中的Field默认有public static final修饰,必须在声明时指定初始值
//final修饰的变量必须在声明时/初始块中指定,但接口又不能有初始化块,那必须在声明时指定了
//String name; //接口的所有成员都需要提供给外部类、包访问,接口公开的标准必须由public修饰
//private double weight = 99; //接口中的方法默认有public abstract修饰
void info(); //抽象方法不能有方法体
//void test(){}
}
接口的继承:
一个接口可以有N个直接父接口;
接口可用于定义变量;不能直接创建实例;提供其他类来实现自己。
implements:实现一个或N个接口,接口实现类要么为接口所有的抽象方法提供实现,否则你的实现类也只能是抽象类。接口主要是在"面向接口编程"时提供更好、更灵活的机制。
interface IEatable{
void eat();
} interface IFlyable{
void fly();
} interface Iwalkable extends IEatable{
int age = 20;
void info();
/*
接口中的方法必须为抽象方法
public static void main(String[] args){
Iwalkable iw = new Sparrow();
}
*/
} public class Sparrow implements IFlyable,Iwalkable{
//因为Sparrow实现了两个接口,所以它必须实现两个接口的所有方法
@Override
public void eat(){
System.out.println("这只麻雀在一口一口吃麦子");
} public void fly(){
System.out.println("这麻雀在飞走了!");
} public void info(){
System.out.println("这是一只小小麻雀");
} public static void main(String[] args){
//向上转型,iw引用变量编译时只是Iwalkable类型,编译器只能允许它调用Iwalkable内的方法
Iwalkable iw = new Sparrow();
iw.info();
iw.eat();
//iw编译时为Iwalkable类型,直接调用fly方法会报错
//iw.fly(); //Sparrow sp = new Sparrow();
//强制向下转型
Sparrow sp = (Sparrow)iw;
sp.fly(); IFlyable ia = new Sparrow();
ia.fly();
}
}
接口与抽象类之间的相似之处:
①、都可以包含抽象方法;
②、都不能创建实例
③、子类抽象类或实现接口,都要求实现所有抽象方法,否则这个子类也只能是抽象类
接口与抽象类之间的区别:
①、接口里只能有抽象方法,而抽象类中可以没有抽象方法也可以包含普通方法;
②、接口中不能定义static方法,而抽象类中可以包含static方法;
③、接口的Field默认有public static final三个修饰符修饰,而抽象类的Field完全可以是普通Field;
④、接口不能包含构造器,而抽象类完全可以有构造器(供子类至少调用一次);
⑤、接口不能包含初始化块,而抽象类完全可以有初始化块;
⑥、接口可以有多个直接的父接口,而抽象类只能有一个直接的父类。
疯狂java学习笔记之面向对象(九) - 抽象和接口的更多相关文章
- 疯狂java学习笔记之面向对象(八) - static和final
一.static: 1.static是一个标识符: - 有static修饰的成员表明该成员是属于类的; - 没有static修饰的成员表明该成员是属于实例/对象的. 2.static修饰的成员(Fie ...
- 疯狂java学习笔记之面向对象(一) - 定义类、方法、构造器
Java面向对象 1.定义类 2.创建对象.调用方法 类和对象: 某一类对象的概念定义. 比如:人类 - 抽象出来的概念(不特指某个人) 对象 - 在类的概念下产生的一个实例,它就是一个对象了. ja ...
- 疯狂java学习笔记之面向对象(六) - 构造器重载、方法重载和方法重写
一.方法重载(Overload): Java允许同一个类中定义多个同名方法,只要形参不一样就可以,如果同一个类中包含了两个或两个以上方法名相同的方法,但形参列表不同,则被成为方法重载(两同一异). 同 ...
- 疯狂java学习笔记之面向对象(五) - 封装、继承、多态
一.封装: 封装的概念: - 合理的隐藏:隐藏不想被外界操作的Field.方法.构造器 - 合理的暴露:一般就是希望给别人调用的方法 e.g:显示器(按键暴露出来操作,但实际的东西/细节方法被隐藏起来 ...
- 疯狂java学习笔记之面向对象(四) - this关键字
Java中this关键字主要有以下两个方法: 1.this引用 - 可用于任何非static修饰的方法和构造器中,当this用于方法中时,它代表调用该方法的实例/对象;当this用于构造器中时,它代表 ...
- 疯狂java学习笔记之面向对象(三) - 方法所属性和值传递
方法的所属性: 从语法的角度来看:方法必须定义在类中 方法要么属于类本身(static修饰),要么属于实例 -- 到底是属于类还是属于对象? 有无static修饰 调用方法时:必须有主调对象(主语,调 ...
- 疯狂java学习笔记之面向对象(二) - 成员变量与局部变量
Java变量按其作用域可分为:成员变量和局部变量.注意:在Java中是没有全局变量这个概念的 一.成员变量: 成员变量是在类中定义的变量,具体可分为类变量与实例变量--有无static修饰 实例变量的 ...
- 疯狂java学习笔记之面向对象(七) - super关键字
super有以下两大作用: 1.起限定作用:强制去访问父类的成员(Field.方法) 2.起调用作用:指定/显示调用父类的某个构造器 super调用规则: 1.子类构造器总会调用父类构造器一次,默认情 ...
- Java学习笔记之---面向对象
Java学习笔记之---面向对象 (一)封装 (1)封装的优点 良好的封装能够减少耦合. 类内部的结构可以自由修改. 可以对成员变量进行更精确的控制. 隐藏信息,实现细节. (2)实现封装的步骤 1. ...
随机推荐
- ASP.NET Ajax 简单实例
本实例讲解Ajax 调用WCF服务. 1.建立一个网站,并在其中添加一个WCF服务(这里需要选择Ajax-Enabled WCF Service). 2.IDE会自动生成一个SVC文件. 3.服务代码 ...
- "稀奇古怪的"delete this
myClass::foo(){ delete this; } .. void func(){ myClass *a = new myClass(); a->foo(); ...
- kmp
#include <bits/stdc++.h> #define MAXN 100000 using namespace std; string a, b; int next[MAXN]; ...
- 【转载】python super的用法
转载地址: http://blog.csdn.net/cxm19830125/article/details/20610533 super的用法是调用继承类的初始化方法,如下面的代码: class A ...
- 几年前做家教写的C教程(之一)
C语言学习宝典 首先让我们认识什么是C语言. C语言是一种计算机开发语言,是一种非常基础的开发语言.能够用C语言做很多事情.C语言是顺序执行的程序. 程序应该包括数据描述,数据操作. C语言的数据类型 ...
- SOA 架构中的ESB是更好的应用于异构系统集成整合还是用于统一服务调用/基础服务实施
一.讨论主题与观点 写一篇文章.发现一次自觉得有意思的SOA架构方面的讨论,源于昨天AgileEAS.NET SOA 平台群(113723486)里几个群友的一次关于ESB的一次讨论. 大家的讨论观点 ...
- 注解:【有连接表的】Hibernate单向N->1关联
Person与Address关联:单向N->1,[有连接表的] Person.java package org.crazyit.app.domain; import javax.persiste ...
- java线程之——synchronized的注意细节
我在学习synchronized的时候,十分好奇当一个线程进入了一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 然后就做了个实验(实验代码最后贴出),最后得到了如下 ...
- linux下vim配置以及一些常用的快捷键
一些常用的vim编辑器快捷键: h」.「j」.「k」.「l」,分别控制光标左.下.上.右移一格. 按「ctrl」+「b」:屏幕往“后”移动一页. 按「ctrl」+「f」:屏幕往“前”移动一页. 按「c ...
- API和系统调用实现同一方法
“平安的祝福 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 一.基 ...