1.继承
例如一个员工类,包括开发员工和经理。
package cn.jxufe.java.chapter2.demo12; public class Employee { String name; public void work() { System.out.println("员工在工作..."); } }
package cn.jxufe.java.chapter2.demo12; /* * 定义研发部员工 * 属于员工中的一种 * 研发员工继承员工类 * * 关键字 extends * 子类是Developer, 父类是Employee * 子类自动拥有父类中可以继承的属性和方法 * * 子类中,可以直接调用父类的成员 */ public class Developer extends Employee { public void print() { System.out.println("the name of Developer is " + name); } }
package cn.jxufe.java.chapter2.demo12; public class Manager extends Employee { public void printf() { System.out.println("the name of Manager is " + name); } }
package cn.jxufe.java.chapter2.demo12; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub Developer d = new Developer(); d.name = "开发者"; d.print(); Manager m = new Manager(); m.name = "经理"; m.printf(); d.work(); m.work(); } }
继承的好处:
1、继承的出现提高了代码的复用性,提高软件开发效率。
2、继承的出现让类与类之间产生了关系,提供了多态的前提。
2.变量的隐藏和方法的覆盖
2.1变量的隐藏
package cn.jxufe.java.chapter3.demo2; public class Student { String name = "student"; }
package cn.jxufe.java.chapter3.demo2; public class CollegeStudent extends Student { String name = "CollegeStudent"; public void printName() { System.out.println("collegeStudent name is " + name); System.out.println("student name is " + super.name); } }
package cn.jxufe.java.chapter3.demo2; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub CollegeStudent collegeStudent = new CollegeStudent(); System.out.println(collegeStudent.name); collegeStudent.printName(); } }
2.2方法的重写
举例:
比如手机,当描述一个手机时,它具有发短信,打电话,显示来电号码功能,后期由于手机需要在来电显示功能中增加显示姓名和头像,这时可以重新定义一个类描述智能手机,并继承原有描述手机的类。并在新定义的类中覆盖来电显示功能,在其中增加显示姓名和头像功能。
注意:
package cn.jxufe.java.chapter3.demo3; public class Phone { public void sendMessage() { System.out.println("发短信"); } public void call() { System.out.println("打电话"); } public void showNum() { System.out.println("来电显示号码"); } }
package cn.jxufe.java.chapter3.demo3; //智能手机类 public class NewPhone extends Phone { // 覆盖父类的来电显示号码功能,并增加自己的显示姓名和图片功能 public void showNum() { // 调用父类已经存在的功能使用super super.showNum(); // 增加自己特有显示姓名和图片功能 System.out.println("显示来电姓名"); System.out.println("显示头像"); } }
package cn.jxufe.java.chapter3.demo3; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub new NewPhone().showNum(); } }
3.super关键字
3.1调用父类的构造方法
package cn.jxufe.java.chapter3.demo4; public class Person { String color; String language; public Person(String color, String language) { // TODO Auto-generated constructor stub this.color = color; this.language = language; } }
package cn.jxufe.java.chapter3.demo4; public class ChinesePerson extends Person { int age; // String color; // String language; 注意子类中不要再重新定义这两个属性了,否则出错 public ChinesePerson(String color, String language, int age) { // TODO Auto-generated constructor stub super(color, language); this.age = age; } }
package cn.jxufe.java.chapter3.demo4; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub ChinesePerson chinesePerson = new ChinesePerson("yellow", "chinese", 20); System.out.println(chinesePerson.color); System.out.println(chinesePerson.age); } }
3.2调用父类的方法(用于重写了父类的方法)
2.2中已经应用。
4.抽象类和抽象方法
4.1抽象类和抽象方法的产生
当编写一个类时,我们往往会为该类定义一些方法,这些方法是用来描述该类的功能具体实现方式,那么这些方法都有具体的方法体。
但是有的时候,某个父类只是知道子类应该包含怎么样的方法,但是无法准确知道子类如何实现这些方法。比如一个图形类应该有一个求周长的方法,但是不同的图形求周长的算法不一样。那该怎么办呢?
分析事物时,发现了共性内容,就出现向上抽取。会有这样一种特殊情况,就是方法功能声明相同,但方法功能主体不同。那么这时也可以抽取,但只抽取方法声明,不抽取方法主体。那么此方法就是一个抽象方法。
4.2抽象类和抽象方法的定义
/* 抽象方法定义的格式: public abstract 返回值类型 方法名(参数); 抽象类定义的格式: abstract class 类名 { } */
package cn.jxufe.java.chapter3.demo5; /* * 定义类开发工程师类 * EE开发工程师 : 工作 * python开发工程师 : 工作 * * 根据共性进行抽取,然后形成一个父类Developer * 定义方法,工作: 怎么工作,具体干什么呀 * * 抽象类,不能实例化对象, 不能new的 * 不能创建对象的原因: 如果真的让你new了, 对象.调用抽象方法,抽象方法没有主体,根本就不能运行 * 抽象类使用: 定义类继承抽象类,将抽象方法进行重写,创建子类的对象 */ public abstract class Developer { public abstract void work(); }
package cn.jxufe.java.chapter3.demo5; public class JavaEE extends Developer { public void work() { System.out.println("JavaEE工程师在工作..."); } }
package cn.jxufe.java.chapter3.demo5; public class Python extends Developer { public void work() { System.out.println("Python工程师在工作..."); } }
package cn.jxufe.java.chapter3.demo5; /* * 测试抽象类 * 创建他的子类的对象,使用子类的对象调用方法 */ public class Test { public static void main(String[] args) { JavaEE ee = new JavaEE(); ee.work(); Python py = new Python(); py.work(); } }
1. 抽象类中是否可以不定义抽象方法?
是可以的,那这个抽象类的存在到底有什么意义呢?不让该类创建对象,方法可以直接让子类去使用。
2. 抽象关键字abstract不可以和哪些关键字共存?
1、private:私有的方法子类是无法继承到的,也不存在覆盖,而abstract和private一起使用修饰方法,abstract既要子类去实现这个方法,而private修饰子类根本无法得到父类这个方法。互相矛盾。
2、final,暂时不关注,后面学
3、static,暂时不关注,后面学
5.抽象类案例简单应用
5.1案例描述
某IT公司有多名员工,按照员工负责的工作不同,进行了部门的划分(研发部员工、维护部员工)。研发部根据所需研发的内容不同,又分为JavaEE工程师、Android工程师;维护部根据所需维护的内容不同,又分为网络维护工程师、硬件维护工程师。
公司的每名员工都有他们自己的员工编号、姓名,并要做它们所负责的工作。
工作内容:
- JavaEE工程师:员工号为xxx的 xxx员工,正在研发淘宝网站
- Android工程师:员工号为xxx的 xxx员工,正在研发淘宝手机客户端软件
- 网络维护工程师:员工号为xxx的 xxx员工,正在检查网络是否畅通
- 硬件维护工程师:员工号为xxx的 xxx员工,正在修复打印机
请根据描述,完成员工体系中所有类的定义,并指定类之间的继承关系。进行XX工程师类的对象创建,完成工作方法的调用。
5.2案例分析
5.3案例实现
package cn.jxufe.java.chapter3.demo6; public abstract class Employee { private String id;// 员工编号 private String name; // 员工姓名 public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } // 工作方法(抽象方法) public abstract void work(); }
package cn.jxufe.java.chapter3.demo6; // 定义研发部员工类Developer 继承 员工类Employee public abstract class Developer extends Employee { }
package cn.jxufe.java.chapter3.demo6; public abstract class Maintainer extends Employee{ }
package cn.jxufe.java.chapter3.demo6; public class JavaEE extends Developer { @Override public void work() { System.out.println("员工号为 " + getId() + " 的" + getName() + "员工,正在研发淘宝网站"); } }
package cn.jxufe.java.chapter3.demo6; public class Android extends Developer { @Override public void work() { System.out.println("员工号为 " + getId() + " 的 " + getName() + " 员工,正在研发淘宝手机客户端软件"); } }
package cn.jxufe.java.chapter3.demo6; public class Hardware extends Maintainer { @Override public void work() { System.out.println("员工号为 " + getId() + " 的 " + getName() + " 员工,正在修复打印机"); } }
package cn.jxufe.java.chapter3.demo6; public class Network extends Maintainer { @Override public void work() { System.out.println("员工号为 " + getId() + " 的 " + getName() + " 员工,正在检查网络是否畅通"); } }
package cn.jxufe.java.chapter3.demo6; public class Test { public static void main(String[] args) { // 创建JavaEE工程师员工对象 JavaEE ee = new JavaEE(); // 设置该员工的编号 ee.setId("000015"); // 设置该员工的姓名 ee.setName("小明"); // 调用该员工的工作方法 ee.work(); } }
6.接口
6.1接口的概念
6.2接口的定义
例子:
狗的叫声是“汪汪汪”,猫的叫声是“喵喵喵”,羊的叫声是“咩咩咩”。将动物中叫这种行为定义为对外接口。
package cn.jxufe.java.chapter3.demo7; public interface Shout { void shoutSound(); // 和public abstract void shoutSound() 等价 }
6.3接口的实现
package cn.jxufe.java.chapter3.demo7; public class Dog implements Shout { public void shoutSound() { // TODO Auto-generated method stub System.out.println("狗的叫声是“汪汪汪”"); } }
package cn.jxufe.java.chapter3.demo7; public class Cat implements Shout { public void shoutSound() { // TODO Auto-generated method stub System.out.println("猫的叫声是“喵喵喵”"); } }
package cn.jxufe.java.chapter3.demo7; public class Sheep implements Shout { // @Override 注意不是重写这个功能,而是实现,加这个将报错 public void shoutSound() { // TODO Auto-generated method stub System.out.println("羊的叫声是“咩咩咩”"); } }
package cn.jxufe.java.chapter3.demo7; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub new Dog().shoutSound(); new Cat().shoutSound(); new Sheep().shoutSound(); } }
6.4Comparable接口
package cn.jxufe.java.chapter3.demo7; import java.util.Date; public class TestComparable { public static void main(String[] args) { // TODO Auto-generated method stub System.out.println(new Integer(3).compareTo(new Integer(5))); System.out.println("ABC".compareTo("ABE")); System.out.println("ABC".compareTo("ABF")); Date date1 = new Date(2013, 1, 1); Date date2 = new Date(2012, 1, 1); System.out.println(date1.compareTo(date2)); } }
package cn.jxufe.java.chapter3.demo7; import java.math.BigInteger; import java.util.Arrays; public class TestSortComparable { public static void main(String[] args) { // TODO Auto-generated method stub String[] cities = { "nanchang", "beijing", "shanghai", "xuzhou", "nanjing" }; Arrays.sort(cities); for (String city : cities) System.out.print(city + " "); System.out.println(); BigInteger[] hugeNumbers = { new BigInteger("232323199305142015"), new BigInteger("323199305142015"), new BigInteger("45213549679215") }; Arrays.sort(hugeNumbers); for (BigInteger number : hugeNumbers) System.out.print(number + " "); } }
package cn.jxufe.java.chapter3.demo7; import java.util.Arrays; public class TestComparableRectangle implements Comparable<TestComparableRectangle> { double height; double width; public TestComparableRectangle(double height, double width) { // TODO Auto-generated constructor stub this.height = height; this.width = width; } public double getArea() { return height * width; } @Override public int compareTo(TestComparableRectangle o) { // TODO Auto-generated method stub if (getArea() > o.getArea()) return 1; else if (getArea() < o.getArea()) return -1; else return 0; } @Override public String toString() { // TODO Auto-generated method stub return "with: " + width + " height " + height + " Area: " + getArea(); } public static void main(String[] args) { // TODO Auto-generated method stub TestComparableRectangle[] rectangles = { new TestComparableRectangle(3.4, 5.4), new TestComparableRectangle(13.24, 55.4), new TestComparableRectangle(7.4, 35.4), new TestComparableRectangle(1.4, 22.4) }; Arrays.sort(rectangles); for (TestComparableRectangle rectangle : rectangles) System.out.println(rectangle); } }
6.5Comparator接口
package cn.jxufe.java.chapter3.demo7; import java.util.Comparator; public class GeometricObjectComparator implements Comparator<GeometricObject> { @Override public int compare(GeometricObject o1, GeometricObject o2) { // TODO Auto-generated method stub double area1 = o1.getArea(); double area2 = o2.getArea(); if (area1 < area2) return -1; else if (area1 == area2) return 0; else return 1; } public static void main(String[] args) { GeometricObject g1 = new Rectangle(5, 5); GeometricObject g2 = new Circle(5); GeometricObject g = max(g1, g2, new GeometricObjectComparator()); System.out.println("the area of the larger object is " + g.getArea()); } public static GeometricObject max(GeometricObject g1, GeometricObject g2, Comparator<GeometricObject> c) { if (c.compare(g1, g2) > 0) return g1; else return g2; } }
7.接口的应用小例子
package cn.jxufe.java.chapter3.demo8; public interface Ishape { double PI = 3.14159; // 和public static final double PI = 3.14159等价 double getArea(); // 和public abstract double getArea()等价 double getPerimeter(); }
package cn.jxufe.java.chapter3.demo8; public class Circle implements Ishape { double redius; public Circle(double redius) { // TODO Auto-generated constructor stub this.redius = redius; } public double getArea() { return redius * redius * PI; } public double getPerimeter() { return 2 * redius * PI; } }
package cn.jxufe.java.chapter3.demo8; public class Rectangle implements Ishape { double height; double wight; public Rectangle(double height, double wight) { // TODO Auto-generated constructor stub this.height = height; this.wight = wight; } public double getArea() {//必须用public权限 return height * wight; } public double getPerimeter() { return 2 * (height + wight); } }
package cn.jxufe.java.chapter3.demo8; public class Triangle implements Ishape { double a, b, c; public Triangle(double a, double b, double c) { // TODO Auto-generated constructor stub this.a = a; this.b = b; this.c = c; } public double getArea() { double s = 0.5 * (a + b + c); return Math.sqrt(s * (s - a) * (s - b) * (s - c)); } public double getPerimeter() { return a + b + c; } }
package cn.jxufe.java.chapter3.demo8; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub Circle circle = new Circle(10); System.out.println("circle area is " + circle.getArea() + " circle perimeter is " + circle.getPerimeter()); Rectangle rectangle = new Rectangle(10, 20); System.out.println( "Rectangle area is " + rectangle.getArea() + " rectangle perimeter is " + rectangle.getPerimeter()); Triangle triangle = new Triangle(3, 4, 5); System.out.println( "triangle area is " + triangle.getArea() + " triangle perimeter is " + triangle.getPerimeter()); } }
8.接口的多实现
package cn.jxufe.java.chapter3.demo9; public interface A { public abstract void a(); public abstract void b(); }
package cn.jxufe.java.chapter3.demo9; public interface B { public abstract void a(); }
package cn.jxufe.java.chapter3.demo9; public class C implements A,B{ public void a() { System.out.println("print a"); } public void b() { // TODO Auto-generated method stub System.out.println("pringt b"); } }
package cn.jxufe.java.chapter3.demo9; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub C c = new C(); c.a(); c.b(); } }
9. 类继承类同时实现接口
接口和类之间可以通过实现产生关系,同时也学习了类与类之间可以通过继承产生关系。当一个类已经继承了一个父类,它又需要扩展额外的功能,这时接口就派上用场了。
子类通过继承父类扩展功能,通过继承扩展的功能都是子类应该具备的基础功能。如果子类想要继续扩展其他类中的功能呢?这时通过实现接口来完成。
class Fu { public void show(){} } interface Inter { pulbic abstract void show1(); } class Zi extends Fu implements Inter { public void show1() { } }
接口的出现避免了单继承的局限性。父类中定义的事物的基本功能。接口中定义的事物的扩展功能。
10. 接口的多继承
学习类的时候,知道类与类之间可以通过继承产生关系,接口和类之间可以通过实现产生关系,那么接口与接口之间会有什么关系。
多个接口之间可以使用extends进行继承。
interface Fu1{ void show(); } interface Fu2{ void show1(); } interface Fu3{ void show2(); } interface Zi extends Fu1,Fu2,Fu3{ void show3(); }
在开发中如果多个接口中存在相同方法,这时若有个类实现了这些接口,那么就要实现接口中的方法,由于接口中的方法是抽象方法,子类实现后也不会发生调用的不确定性。
11.接口的思想
前面学习了接口的代码体现,现在来学习接口的思想,接下里从生活中的例子进行说明。
举例:
我们都知道电脑上留有很多个插口,而这些插口可以插入相应的设备,这些设备为什么能插在上面呢?主要原因是这些设备在生产的时候符合了这个插口的使用规则,否则将无法插入接口中,更无法使用。发现这个插口的出现让我们使用更多的设备。
总结:接口在开发中的它好处
1、接口的出现扩展了功能。
2、接口其实就是暴漏出来的规则。
3、接口的出现降低了耦合性,即设备与设备之间实现了解耦。
接口的出现方便后期使用和维护,一方是在使用接口(如电脑),一方在实现接口(插在插口上的设备)。例如:笔记本使用这个规则(接口),电脑外围设备实现这个规则(接口)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)