前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >类与对象(一)—— 类(继承)

类与对象(一)—— 类(继承)

作者头像
东边的大西瓜
发布于 2022-05-05 03:28:06
发布于 2022-05-05 03:28:06
39500
代码可运行
举报
文章被收录于专栏:吃着西瓜学Java吃着西瓜学Java
运行总次数:0
代码可运行

类与对象(一)

不是吧,都2020年,不会还有人没找到对象吧。

(我们先来回顾一下面向对象程序设计的一些知识点)

首先面向对象的程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分。从根本上说,只要对象能够满足功能,那么就不必关心对象的具体实现。OOP将数据放在第一位,然后再考虑操作数据的算法。

西瓜籽:“既然Java是一门OOP语言,那么对象是从哪里来的呢?”

大西瓜:“类是构造对象的模板,由类构造对象的过程称为创建类的实例。可以说对象是类的实例!”

在类与类之间,最常见的关系有:

  • 继承
  • 依赖
  • 聚合

下面我们就来具体的了解下它们:

继承

继承,即“is-a”关系,是一种用于表示特殊与一般关系的。关键字 extends ,表明正在构造的新类派生于一个已存在的类,这个类包括现有类型的所有成员(尽管private成员被隐藏了起来,并且不能被访问)。引入父类(超类)和子类两个术语。

下面我们来用Animal类、Bird类、Fish类来说明下:

Animal类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Animal {
     private int age;
     String name;
     public  Animal(){
     }
     public Animal(String name){
         this.name=name;
     }
     public void getName(){
         System.out.println("我的名字是:"+name);
     }
        public String setName(){
            return name;
        }

     void eating(){
         System.out.println("我要吃饭");
     }
     void calling(){
         System.out.println("我有叫声");
        }

        public int getAge() {
         return age;
     }

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

Bird类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Bird extends Animal {
    public Bird(){
       super("小鸟");
    }

   @Override
   void calling() {
       System.out.println("我的叫声是:啾啾...");
   }
   void flying(){
       System.out.println("我会飞!");
   }
}

Fish类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 public class Fish extends Animal {
      public Fish(){
          super("小鱼");
      }

      @Override
      void calling() {
          System.out.println("咕噜咕噜...");
      }
      void swimming(){
          System.out.println("我会游泳!");
      }
 }

Test测试类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] args) {
      //鸟
      Bird bird = new Bird();
      bird.getName();
      bird.calling();
      bird.flying();

      System.out.println();

      //鱼
      Fish fish = new Fish();
      fish.getName();
      fish.calling();
      fish.swimming();
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输出结果:

我的名字是:小鸟
我的叫声是:啾啾...
我会飞!

我的名字是:小鱼
我的叫声是:咕噜咕噜...
我会游泳!

往上翻,我们在Animal类中定义了一个private修饰的int age:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private int age;

这里就是为了解释 “这个类包括现有类型的所有成员(尽管private成员被隐藏了起来,并且不能被访问)”,这句话是引用于《Java编程思想第四版》。在一些资料中我们经常可以看到这样一句话“子类拥有父类非 private 的属性、方法。”其实你仔细品一下下面这段代码,你会发现这句话是有些问题的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bird.setAge(2);
System.out.println("我是小鸟,我已经"+bird.getAge()+"岁了!");
System.out.println("我是小鱼,我已经"+fish.getAge()+"岁了!");
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输出结果:
我是小鸟,我已经2岁了!
我是小鱼,我已经0岁了!

通过代码我们发现,其实是可以通过brid对象和fish对象,对age字段进行赋值和取值。而且我们通过bird进行的setAge操作并未对fish对象造成影响,结果是初始状态0。 所以我们不难得出,子类对象其实是拥有父类对象中所有的所有成员的,只是父类对象中的私有属性和方法,子类无法访问而已,只是拥有,但不能使用。 就像有些东西你可能拥有,但是你并不能使用。所以子类对象是绝对大于父类对象的所谓的子类对象只能继承父类非私有的属性及方法的说法是错误的。可以继承,只是无法访问到而已。

西瓜籽:“不对啊,你这里说子类无法访问父类的私有成员啊,那为啥上面那段代码的却有结果?”

大西瓜:“我在Animal类中声明了set/get方法来对私有的age变量来进行操作。”

西瓜籽:“子类并没有可使用的age啊,你这不是在对父类Animal进行操作吗?”

大西瓜:“看来你还是不能理解 子类拥有父类所有成员 这句话啊,我再给你掰扯一下,子类在创建的时候会把父类里的成员变量和方法也加载进内存,也就是说在子类的内存中是有age的,我们就可以通过set/get方法对age进行操作。然后用this和super这两个引用来区分是父类的还是子类的,但是这个内存区域是子类的内存区域。this范围大于等于super。还有就是,因为父类数据要加载进子类内存,所以创建子类时会先调用父类的构造函数,来对这些数据进行相应的初始化操作。要注意的是,这里的调用父类构造函数可不是创建一个父类对象啊,真的就只是执行了构造函数,但是内存中并未new一个父类对象。

西瓜籽:“原来是这样啊!我懂了,大西瓜真菜!”

大西瓜:“我xx你个xx...”

强制类型转换

“为新的类提供方法”并不是继承技术中最重要的方面,其最重要的方面是用来表现新类和基类之间的关系。这种关系可以用“新类是现有类的一种类型”这句话加以概括。——《Java编程思想第四版》

既然讲到继承了,当然要来聊一下向上转型向下转型(不被编译器允许)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   //这里使用的是Junit5进行测试
   @org.junit.jupiter.api.Test
   public void test(){
         Animal animal = new Bird();
            animal.getName();
         animal.calling();
            //annimal无flying()方法
            //animal.flying();
   }
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输出结果:

我的名字是:小鸟

我的叫声是:啾啾...

向上转型:将一个子类的引用赋给一个超类变量,即父类的对象引用指向子类对象。可以理解为小范围指向大范围,这是被编译器所允许的。annimal对象无flying()方法,说明向上转型时,父类只能调用父类方法或者子类覆写后的方法,而子类中的单独方法则是无法调用的。

向下转型:与向上转型相反,将一个超类的引用赋给一个子类变量,即子类的对象引用指向父类对象。这时就是大范围指向小范围了,只是不被编译器允许的。

依赖

依赖,即"uses-a"关系,是一种最明显、最常见的关系。即一个类的实现需要依赖于另一个类。属于弱关联关系。

我们用学生需要英语老师,教英语来说明该关系。

Student类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Student {
    public Student(){};
    //使用形参方式发生依赖关系,还可以使用局部变量和静态变量方式   
    public void learn(Teacher teacher){
    System.out.println("我需要"+teacher.getSubject()+"老师,"+teacher.teaching());
     }
}  

Teacher类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Teacher {
      private String subject;
      public Teacher(){}
      public Teacher(String subject){
        this.subject=subject;
      }
      public String teaching(){
        return "教我"+subject;
      }

     public String getSubject() {
         return subject;
     }

     public void setSubject(String subject) {
         this.subject = subject;
     }
} 

Test测试类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 public class Test {
     public static void main(String[] args) {
         Student student = new Student();
         student.learn(new Teacher("英语"));
     }
 }
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输出结果:我需要英语老师,教我英语

注意:我们在实际开发的时候应尽可能的减少这种关系的使用,以降低耦合度。

聚合

聚合,即“has-a”关系,是一种具体且易于理解的关系。聚合关系意味着类A的对象包含类B的对>象。属于强关联关系。

这时我们只需要改动下依赖关系中的Student类和Test测试类就可以实现这种关系。

Student类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  public class Student {
       public Student(){};
       //添加一个构造方法,用来初始化teacher
       public Student(Teacher teacher){
            this.teacher=teacher;
       };
       Teacher teacher;
       public void learn(){
         System.out.println("我需要"+teacher.getSubject()+"老师,"+teacher.teaching());
       }
  }

Test测试类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Test {
   public static void main(String[] args) {
       Teacher teacher = new Teacher("英语");
       Student student = new Student(teacher);
       student.learn();
   }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输出结果:

我需要英语老师,教我英语

注意:我们在实际开发的时候更应尽可能的减少这种关系的使用,以降低耦合度。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-09-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 吃着西瓜学Java 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 类与对象(一)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档