java学习-day03

记录一下曾经学习java的过程-仅供个人参考

继承

继承的概念

一个类继承另外一个类,被继承的类称之为父类、基类、超类,继承的类称之为子类、派生类。

继承的特征

public class F {
   
   private String name;//只有同类中可以访问

   public F() {
      System.out.println("F is init...");
   }

   public void show(){
      System.out.println("F is show...");
   }

}

class S extends F{
   public S() {
      super(); //缺省的调用父类的无参构造函数
      System.out.println("S is init...");
   }
}

测试:

public class Test {
   public static void main(String[] args) {
      S s = new S();
      s.show();
   }
}

输出结果:

F is init...
S is init...
F is show...

1、子类继承父类将继承父类的所有属性和方法,私有的(private)不能直接访问。需要通过接口访问。

2、要想创建子类对象,必先创建父类对象

3、类的继承是单继承、一个类只能直接接触一个父类,可以间接继承多个父类

间接继承
在这里插入图片描述

supper

1.可以通过supper关键字调用父类的属性和方法

2.可以通过supper关键字调用父类的构造函数,只能在子类的构造函数中调用父类的构造函数,必须是在第一行

class F{
   public F(){
      System.out.println("F 1");
   }
   public F(int i){
      System.out.println("F 2");
   }
}
class S extends F{
   public S(){
      // 默认是调用父类的无参构造函数 supper();
      super(10);
      System.out.println("S 1");
   }
   public S(int i){
      System.out.println("S 2");
   }
}
public class Test {
   public static void main(String[] args) {
      new S(); // F 2 => S 1
      new S(10); //F 1=> S 2
   }
}

this和supper使用

在这里插入图片描述

继承的总结

  1. 子类继承父类,继承了父类的所有属性和方法(包含私有的),私有的不能直接访问;
  2. 一个类如果没有使用 extends,那么它将继承 Object 类, Object 类是所有类的父类,始祖类;
  3. 一个类可以继承多个类,但 java 中规定一个类只能直接继承一个类;可以间接继承;
  4. 子类具有扩展的功能,扩展子类特有的属性和方法;
  5. 继承大大提供了代码的重复利用性;

为什么要继承:

java通过继承的机制实现了解决代码冗余、提高了代码的复用性、提高了程序的扩展性

JDK的继承

Object类

所有的类都是Object类的子类,java中如果说没有显示的 继承一个类,那么这个类缺省的继承了Object类,Object类叫做始祖类

在这里插入图片描述

案例:

需求:

银行需要去保存用户的基本信息,银行对于用户有详细的分类:普通用户、VIP用户、大客户

分析:

普通用户:

属性:姓名、性别、出生年月、身份证、电话、账户

方法:存款、取款

VIP用户:

属性:姓名、性别、出生年月、身份证、电话、账户、房屋编码、行驶证编码

方法:存款、取款、贷款

大客户:

属性:姓名、性别、出生年月、身份证、电话、账户、纳税人识别码

方法:存款、取款、贷款、开承兑

完成代码:

使用一个Account类来表示用户的银行账号信息

public class Account {
   private String code;
   private String pwd;
   private double money;

   public String getCode() {
      return code;
   }

   public void setCode(String code) {
      this.code = code;
   }

   public String getPwd() {
      return pwd;
   }

   public void setPwd(String pwd) {
      this.pwd = pwd;
   }

   public double getMoney() {
      return money;
   }

   public void setMoney(double money) {
      this.money = money;
   }
}

使用一个BaseUser类表示普通用户

import java.util.Date;

public class BaseUser {

   private String name;
   private char sex;
   private Date birth;
   private String phone;
   private Account account;

   /**
    * 存钱
    * @param money
    */
   public void saveMoney(double money) {

   }

   /**
    * 取钱
    * @return
    */
   public Double receiveMoney() {
      return 0.0D;
   }

}

使用VIPUser表示 VIP用户的基本信息

import java.util.Date;

public class VipUser {
   private String name;
   private char sex;
   private Date birth;
   private String phone;
   private Account account;

   private String houseCode;
   private String carCode;

   /**
    * 存钱
    * @param money
    */
   public void saveMoney(double money) {

   }

   /**
    * 取钱
    * @return
    */
   public Double receiveMoney() {
      return 0.0D;
   }


   /**
    * 贷款
    * @param money
    * @return
    */
   public Double loanMoney(double money){
      return 0.0D;
   }
}

使用BigUser表示大客户的信息

import java.util.Date;

public class BigUser {
   private String name;
   private char sex;
   private Date birth;
   private String phone;
   private Account account;

   private String taxpayerCode;//纳税人识别码

   /**
    * 存钱
    * @param money
    */
   public void saveMoney(double money) {

   }

   /**
    * 取钱
    * @return
    */
   public Double receiveMoney() {
      return 0.0D;
   }

   /**
    * 贷款
    * @param money
    * @return
    */
   public Double loanMoney(double money){
      return 0.0D;
   }

   public Double bigMoney(double money){
      return 0.0D;
   }
}

从以上的代码我们可以看到冗余代码,用户的基本信息、存款和取款的操作都是冗余代码

在这里插入图片描述

存款和取款的操作

在这里插入图片描述

使用继承的思想来解决代码冗余的问题

继承关系结构

在这里插入图片描述

1.修改VipUser删除和BaseUser共有的代码,是的VipUser继承BaseUser
在这里插入图片描述
2.修改BigUser删除和BaseUser共有的代码,是的VipUser继承BaseUser
在这里插入图片描述
3.删除BigUser 和VipUser 的存款和取款方法,使用父类BaseUser的方法

4.在BaseUser中实现存款和取款的方法

   /**    * 存钱    *    * @param money    */   
   public void saveMoney(double money) {      
   //实现存款的业务      
   //用户账户的余额和存入的金额相加      
   double add = this.account.getMoney() + money;      
   //将得到的结果set到Account中      
   this.account.setMoney(add);   
}
      /**
    * 取钱
    *
    * @return
    */
   public Double receiveMoney(double money) {
      //获取余额
      double restMoney = account.getMoney();
      //用余额- 取款的金额
      restMoney = restMoney - money;

      //判断余额是否<0 : 如果<0 则取款失败 返回用户取款0元 提示用户重新输入余额
      if (restMoney < 0) {
         System.out.println("余额不足,仅剩余额:" + (restMoney + money));
         return 0.0D;
      }
      //重新设置余额
      account.setMoney(restMoney);
      return money;
   }

5.实现基本用户的存款和取款业务 BaseTest

import java.util.Date;

public class BaseTest {
   public static void main(String[] args) {
      //功能1 存款
      // 普通用户存款
      BaseUser user = new BaseUser();
      // 普通用户填写基本信息
      user.setName("jack");
      user.setSex('男');
      Date date = new Date();//获取当前的日期
      user.setBirth(date);
      user.setPhone("18899998888");
      //开户
      Account account = new Account();//申请了一个内存空间
      account.setCode("998");
      account.setPwd("123456");
      account.setMoney(1);
      user.setAccount(account);
      //存款
      user.saveMoney(10000);

      //确认用用户的余额
      System.out.println(user.getName()+"的余额:"+user.getAccount().getMoney());

      //取款
      double money = user.receiveMoney(4000);
      System.out.println(user.getName() + "取款:" + money);
      System.out.println(user.getName()+"的余额:"+user.getAccount().getMoney());
   }
}

6.实现VIP用户的存款和取款业务

import java.util.Date;

public class VipTest {
   public static void main(String[] args) {

      //VIP 用户存款
      VipUser user = new VipUser();//申请了一个内存空间
      //用户填写基本信息
      user.setName("tom");
      user.setSex('女');
      Date date = new Date();//获取当前的日期
      user.setBirth(date);
      user.setPhone("18877887788");
      //开户
      Account account = new Account();//申请了一个内存空间
      account.setCode("997");
      account.setPwd("321321");
      account.setMoney(1);
      user.setAccount(account);

      //存款
      user.saveMoney(5000);
      //确认余额
      System.out.println(user.getName() + "的余额" + user.getAccount().getMoney());
      //取款
      double money = user.receiveMoney(6000);
      System.out.println(user.getName() + "取款:" + money);
      System.out.println(user.getName()+"的余额:"+user.getAccount().getMoney());
   }
}

方法重写

概念

在子类继承父类的关系中,子类的方法名、参数列表、返回值类型全部相同,我们叫做方法重写(Override)

class F{
   public void show(){
      System.out.println("F is show");
   }
}
class S extends F{
   public void show(){
      System.out.println("S is show");
   }
}
public class Test {
   public static void main(String[] args) {
      S s = new S();
      s.show();
   }
}

通过方法重写优化银行业务的代码

1、在VipUser类中重写saveMoney、receiveMoney方法

在这里插入图片描述
在这里插入图片描述

2.测试接口

执行VipTest
在这里插入图片描述

说明调用了是子类的重写方法

抽象

抽象:就是抽取,抽取子类共有的属性和方法到父类。

抽象类是代码重构的结构,是抽象的。实际不存在的

抽象方法:只有方法的声明、没有方法的实现。

抽象类的特征:

1、抽象类是子类共有属性的方法抽象的结果,有abstract关键字来修饰

2、抽象类不能被实例化(new),抽象类有构造函数,而构造函数是用来被子类调用的

3、抽象类可以有实例方法、抽象方法、也可以没有

4、如果一个类继承了一个抽象类,那么这个类必须重写父类的所有抽象方法,包含间接继承。否则这个类也是一个抽象。抽象类可以不重写父类的抽象方法,也可以重写。

在这里插入图片描述

代码实现

abstract class F{
   private String name;

   public F() {
      System.out.println("F is init");
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public void show(){
      System.out.println("F is show");
   }
   //父类提供共有的方法接口 run 有子类来实现
   public abstract void run();

}

class S extends F{

   public S() {
      super();
      System.out.println("S is init");
   }

   @Override
   public void run() {
      System.out.println("S is run");
   }
}

class D extends F{

   public D() {
      super();
      System.out.println("D is init");
   }

   @Override
   public void run() {
      System.out.println("D is run");
   }
}

public class Test {
   public static void main(String[] args) {

      S s = new S();
      s.show();
      s.run();

      D d = new D();
      d.show();
      d.run();

   }
}

运行结果

F is init
S is init
F is show
S is run
F is init
D is init
F is show
D is run

好好理解下面的代码:

abstract class A{
   abstract void show();
}
abstract class B extends A{
   abstract void run();
   @Override
   void show() {
      
   }
}
abstract class C extends B{

}
class D extends B{

   @Override
   void run() {
      
   }
}

public class Test {

}

里氏代换原则

当一个地方需要一个超类对象的时候,我们可以通过一个子类来代替它!

在这里插入图片描述

多态

什么是多态: 一种声明,多种实现!

在这里插入图片描述

编译时多态:体现为方法重载

在编译的时候已经决定了show方法有多种形参的可能性

在这里插入图片描述

运行时多态:体现为方法重写

f在运行的过程中,可以指向子类S的对象,也可以指向子类D 的对象

三大前提条件:

1、必须有继承

2、必须有重写

3、必须有父类的声明指向子类的引用

在这里插入图片描述

例子

案例1:方法重载的应用

在这里插入图片描述

案例2:方法重写

创建一个Persen抽象类

public abstract class Person {
   private String name;
   private int age;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public int getAge() {
      return age;
   }

   public void setAge(int age) {
      this.age = age;
   }
}

创建一个打印类Printer

/**
 * 打印Person
 */
public class Printer {

   /**
    * 打印student和user的属性
    */
   public void show(Person person){
      //打印对象
      System.out.println(person.getName()+"\t"+person.getAge());
   }

}

创建Person 的子类User

public class User extends Person {
}

创建子类Student

public class Student extends Person {
}

测试

public class Test {

   public static void main(String[] args) {

      //多态是用于参数的传递
      Printer f = new Printer();
      Person person = new User();// 多态
      person.setName("jack");
      person.setAge(20);
      f.show(person);//多态

      person = new Student();
      person.setName("小黑");
      person.setAge(18);
      f.show(person);

   }

}

案例3:方法重写 - 工厂模式 - 简单工厂

对象抽象类:

public abstract class Person {
   private String name;
   private int age;

   public Person() {
   }

   //提供给子类进行属性初始化用的
   public Person(String name, int age) {
      this.name = name;
      this.age = age;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public int getAge() {
      return age;
   }

   public void setAge(int age) {
      this.age = age;
   }
}

打印类:打印Person的属性

/**
 * 打印Person
 */
public class Printer {

   /**
    * 打印student和user的属性
    */
   public void show(Person person){
      //打印对象
      System.out.println(person.getName()+"\t"+person.getAge());
   }

}

工厂:根据用户的需求创建所需要的对象

/**
 * 用来创建Person
 */
public class Factory {

   public Person newInstance(String type,String name,int age){
      switch (type){
         case "U":
            return  new User(name,age);
         case "S":
            return new Student(name,age);
         default:
            return null;
      }
   }

}

业务类: 需要打印User的属性

public class User extends Person {

   public User() {
   }

   public User(String name, int age) {
      super(name, age);
   }
}

需求增加:需要打印Student的属性

public class Student extends Person {

   public Student() {
   }

   public Student(String name, int age) {
      super(name, age);
   }
}

测试:

Factory factory = new Factory();//帮助调用者取创建对应的对象
// 创建对象
Person person = factory.newInstance("U","jack",20);
Printer printer = new Printer();
printer.show(person);

工厂模式

工厂模式提高了程序的扩展性。

1、简单工厂

2、工厂方法

3、抽象工厂

需求:

我们需压设计一个汽车4S店的程序:卖奔驰、宝马 汽车可以行驶

step: 使用简单工厂实现 => test06

点评:使用简单工厂模式,我们实现Car解耦,如果需要增加一个比亚车车型的销售,只需要继承Car抽象类重写父类的方法,在工厂中增加比亚迪对象创建!从这个代码我们发现,新增一个成型,工厂类需要重新写是一种强耦合,不利于业务的扩展!

step:使用工厂方法来实现,我们仅需要改造工厂即可 => test07

点评:在实现了对汽车的扩展之外又实现了对工厂的抽象和拓展。新增一个品牌只要实现Car和AbstractFactory即可,生成一个新的4S点 XXXShop

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值