• 面向对象的封装, 构造器, this


    当我们创建一个对象的时候,我们可以通过‘对象、属性’的方式,对对象的属性进行赋值。 这里赋值操作要受到属性的数据类型和存储范围的制约,但是除此之外,没有其他制约条件。 但是实际问题中我们需要给这个属性赋值加入额外的限制条件这个额外条件就不能在属性的声明时体现,我们只能通过方法来进行限制条件的添加

    为什么要用封装呢? 封装的含义是什么?

     为什么需要封装?封装的作用和含义? 
          我要用洗衣机,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内 部的结构吗?有必要碰电动机吗?
          我要开车,…
        我们程序设计追求“高内聚,低耦合”。
        高内聚 :类的内部数据操作细节自己完成,不允许外部干涉;
        低耦合 :仅对外暴露少量的方法用于使用。  隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提 高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露 的暴露出来。这就是封装性的设计思想。

     

    信息的封装和隐藏

    Java中通过将数据声明为私有的(private),再提供公共的(public) 方法:getXxx()和setXxx()实现对该属性的操作,以实现下述目的: 
      隐藏一个类中不需要对外提供的实现细节;
      使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑, 限制对属性的不合理操作;
      便于修改,增强代码的可维护性;

    private :私有的。当对属性加入这个条件的时候就不能直接调用这个方法了

    public class fz {
        public static void main(String[] args) {
            Anim ani =new Anim();
            //ani.age=17;// 因为下面的年龄属性已经设置为私有的了 就不可以直接进行调用不然就以报错
            ani.setAge(13); // 设置年龄只能通过它内部提供的方法
            ani.name = "旺财";
            ani.info();   //名字是: 旺财,age: 13
            System.out.println(ani.getAge());  // 通过内部的获取方法
        }
    }
    
    class Anim{
        private int age;   // 给年龄加上限制条件
        String name;
    
        public void setAge(int num){
            if(num < 0){
                System.out.println("不好意思年龄不可以小于0");
            }else{
                age = num;
            }
        }
    
        public void info(){
            System.out.println("名字是: "+name+"age: "+age);
        }
        public int getAge(){   // 对外部提供一个获取的方法
            return age;
        }
    }

    封装代码性的体现:

      

          1: 我们将类的属性和方法私有化(private)同时,提供了(public)方法来获取(get/set)来获取或者设置此属性的值
    
         2: 不对外暴漏的私有化的方法
         3: 单利模式
         。。。。。。 诸如此类 有多种

    封装行性的体现:

    1、private    2、不对外暴漏私有化方法  3、单例模式

    封装的体现需要权限修饰符来配合:

    java的4种权限(从小到大):private、缺省(什么都不写)、protected、public

    这4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类

      

    修饰类 : 只能使用缺省和public 

     练习:

    创建程序,在其中定义两个类:Person和PersonTest类。定义如下:
    用setAge()设置人的合法年龄(0~130),用getAge()返回人的年龄。 在PersonTest类中实例化Person类的对象b,调用setAge()和 getAge()方法,体会Java的封装性。
    public class Order {
        public static void main(String[] args) {
            PersonTest pt = new PersonTest();
            pt.info(17);
            System.out.println(pt.getinfo());
    
    
    
        }
    }
    
    class PersonTest{
        Person1 per = new Person1();
        public void info(int num){
            per.setAge(num);
        }
    
        public String getinfo() {
            return per.getAge();
        }
    }
    
    class Person1{
        private int age;
    
        public void setAge(int num){
            if(num >= 0 && num <=130 ){
                age = num;
            }else{
                System.out.println("您输入的年龄不合法");
            }
        }
    
    
        public String getAge(){
            return "您输入的年龄是:"+age;
        }
    }

    构造器:

    其实我们之前就接触了构造器只不过是大家不清楚

    Person per = new Person()   // 后面的Person()这个部分就是构造器

    构造器的特征

    它具有与类相同的名称
    它不声明返回值类型。(与声明为void不同) 
    不能被static、finalsynchronizedabstract、native修饰,不能有 return语句返回值

    构造器的作用:

      创建对象,给对象初始化。  也就是构造器一步实现了。python中的__new__和__init__  方法

    构造器的作用:创建对象;给对象进行初始化
    如:Order o = new Order(); Person p = new Person(“Peter”,15);
    如同我们规定每个“人”一出生就必须先洗澡,我们就可以在“人”的 构造器中加入完成“洗澡”的程序代码,于是每个“人”一出生就会自 动完成“洗澡”,程序就不必再在每个人刚出生时一个一个地告诉他们 要“洗澡”了。

    说明:

      

    如果没有现实构造器的话 系统默认提供一个空参数的构造器
    
    构造器格式:
        权限修饰符   类名(形参列表){}
      语法格式:
    修饰符 类名 (参数列表) {
    初始化语句;
    }


    eg: public person(){} //这就是一个简答的构造器

     在实例化类的时候就调用了 这个类的中的默认的构造器,一旦我们定义了构造器系统就不再提供默认的空参数构造器

     构造器的执行:当我们在实例化对象的时候 执行new就去调用了构造器

    构造器重载

    构造器一般用来创建对象的同时初始化对象。如 
      
        class Person{
             String name;
             int age;
             public Person(String n , int a){
                      name=n; age=a;
              }
             }
     构造器重载使得对象的创建更加灵活,方便创建各种不同的对象。 构造器重载举例:
      
      public class Person{
            public Person(String name, int age, Date d) {this(name,age);…}
      
            public Person(String name, int age) {…}
      
            public Person(String name, Date d) {…}
      
            public Person(){…}
            }
     构造器重载,参数列表必须不同

    注意:

    Java语言中,每个类都至少有一个构造器 
    默认构造器的修饰符与所属类的修饰符一致 
    一旦显式定义了构造器,则系统不再提供默认构造器 
    一个类可以创建多个重载的构造器 
    父类的构造器不可被子类继承

    练习:

    1. 在前面定义的Person类中添加构造器,利用构造器设置所有人的age属 性初始值都为18。
    2. 修改上题中类和构造器,增加name属性,使得每次创建Person对象的同 时初始化对象的age属性值和name属性值。
    编写两个类,TriAngle和TriAngleTest,其中TriAngle类中声明私有的底 边长base和高height,
    同时声明公共方法访问私有变量。此外,提供类 必要的构造器。另一个类中使用这些公共方法,计算三角形的面积。

     

    this关键字

    在Java中,this关键字比较难理解,它的作用和其词义很接近。 
     它在方法内部使用,即这个方法所属对象的引用; 
     它在构造器内部使用,表示该构造器正在初始化的对象。 
     this 可以调用类的属性、方法和构造器 
     什么时候使用this关键字呢? 
     当在方法内需要用到调用该方法的对象时,就用this。 具体的:我们可以用this来区分属性和局部变量。 比如:this.name = name;

    this关键字的使用:

    用来修饰 属性、方法、 构造器

    this理解为当前对象

    eg:大家在给对象中的属性赋值的时候你的形参和当前的属性名一样的话 会被覆盖 会默认行参给行参传递参数,那么就需要用到this关键字了

    通常情况下我们都选择省略this,如果方法的形参和属性同名时,我们必须显示使用this方法声明此变量是属性而非行参

    我们可以通过this在另外一个方法中调用另外一个方法

        public PersonTest(int a, String name){
    
            this.getAge();   // 通过this来调用其他方法
            this.name =name;
            age = a;
        }

     

    属性赋值的先后顺序:

      

    1: 默认初始化
    
    2: 显示初始化
    
    3: 构造器中赋值
    
    4: 通过对象.属性的方式
    
        以上操作的先后顺序 1--2--3--4

    this调用构造器 :

    当调用构造器的时候直接this(行参列表);来调用本类的指定的构造器;
    
    构造器中不能通过this(行参列表);的方式调用自己,只能调用别的构造器
    this(行参列表);必须声明在当前构造器的首行,(一个构造器内部只能有一个this调用其他的构造器)
     

     

    注意:

     可以在类的构造器中使用"this(形参列表)"的方式,调用本类中重载的其 他的构造器!
     明确:构造器中不能通过"this(形参列表)"的方式调用自身构造器
     如果一个类中声明了n个构造器,则最多有 n - 1个构造器中使用了 "this(形参列表)""this(形参列表)"必须声明在类的构造器的首行!
     在类的一个构造器中,最多只能声明一个"this(形参列表)"

    练习:

    public class lx {
        public static void main(String[] args) {
            Gol gol = new Gol("梁山伯",23);
            gol.shout();
    
            Girl girl = new Girl("朱丽叶", 38);
            girl.merry(gol);
            girl.compare(girl);
        }
    }
    
    
    class Gol{
        private int age;
        private String name;
    
        public Gol(){
        }
    
        public  Gol(String name){
            this.name = name;
        }
    
        public Gol(String name, int age){
            this.name = name;
            this.age = age;
        }
        public void setAge(int age){
            this.age = age;
        }
        public void setName(String name){
            this.name = name;
        }
        public int getAge(){
            return age;
        }
        public String getName(){
            return name;
        }
        public void merry(Girl girl){
            System.out.println("我想娶:"+girl.getName());
        }
        public void shout(){
            if(this.age > 22){
                System.out.println("你可以娶合法登记了");
            }else{
                System.out.println("滚回去长大了再来");
            }
        }
    
    }
    
    
    class Girl{
        private int age;
        private String  name;
    
        public Girl(){}
        public Girl(String name){
            this.name = name;
        }
        public Girl(String name, int age){
            this.name = name;
            this.age = age;
        }
    
        public void setAge(int age){
            this.age = age;
        }
        public void setName(String name){
            this.name = name;
        }
        public int getAge(){
            return age;
        }
        public String getName(){
            return name;
        }
        public void merry(Gol gol){
            System.out.println("我想嫁给:"+gol.getName());
            gol.merry(this);  // 把当前对象传递进去
        }
    
        /**
         *
         */
        public void compare(Girl girl){
            if(this.age >= girl.age){
                System.out.println("你可以嫁给他了");
            }else{
                System.out.println("不可以你需要再谈谈恋爱");
            }
        }
    
    }
    View Code

    Practice

    1、写一个名为 Account 的类模拟账户。该类的属性和方法如下图所示。该类包括的属性: 
      账号 id,余额 balance,年利率 annualInterestRate;包含的方法:访问器方法(getter 和 setter 方法),
      取款方法 withdraw(),存款方法 deposit()。
      Account
      
      private int id
      private double balance
      private double annualInterestRate
      public Account (int id, double balance, double annualInterestRate )
      public int getId() public double getBalance()

      public double getAnnualInterestRate()

      public void setId( int id)

      public void setBalance(double balance)
       public void setAnnualInterestRate(double annualInterestRate)
       public void withdraw (double amount)//取钱 public void deposit (double amount)//存钱 提示:在提款方法 withdraw 中,需要判断用户余额是否能够满足提款数额的要求,如果不 能,应给出提示。 2. 创建 Customer 类。 Customer   private String
    firstName private

    String lastName
    private Account account
    public Customer(String f,String l)
    public String getFirstName()
    public String getLastName()
    public Account getAccount()
    public void setAccount(Account account) a. 声明三个私有对象属性:firstName、lastName 和 account。
    b. 声明一个公有构造器,这个构造器带有两个代表对象属性的参数(f 和 l)
    c. 声明两个公有存取器来访问该对象属性,方法 getFirstName 和 getLastName 返回相应的属 性。
    d. 声明 setAccount 方法来对 account 属性赋值。
    e. 声明 getAccount 方法以获取 account 属性。
    3.写一个测试程序。
    (1) 创建一个 Customer ,名字叫 Jane Smith, 他有一个账号为 1000,余额为 2000 元, 年利率为 1.23% 的账户。
    (2) 对 Jane Smith 操作。 存入 100 元,再取出 960 元。再取出 2000 元。 打印出 Jane Smith 的基本信息 尚
    public class AprilFourAfternoonTestOne {
        public static void main(String[] args) {
            CustomerTestOne customerTestOne = new CustomerTestOne("Jane","Smith");
            AccountTestOne accountTestOne = new AccountTestOne(01,200,0.0023);
            customerTestOne.setAccount(accountTestOne);
            customerTestOne.getAccount().deposit(100);
            customerTestOne.getAccount().withdraw(120);
        }
    }
    
    
    class AccountTestOne{
        private  int id;
        private double balance;  // 余额
        private double annualInterestRate;  // 年利率
    
        public void withdraw(double amount){ // 取钱
            if(amount <= 0){
                System.out.println("取出的数额不合法");
            }else if(amount > balance){
                System.out.println("取出的数目不合法太大了");
            }else{
                balance -= amount;
                System.out.println("取出: "+amount+"当前余额为:" +balance);
            }
        }
    
        public void deposit(double amount){
            if(amount > 0){
                balance += amount;
                System.out.println("存入: "+amount+"当前余额: "+balance);
            }
        }
    
        public AccountTestOne() {
        }
    
        public AccountTestOne(int id, double balance, double annualInterestRate) {
            this.id = id;
            this.balance = balance;
            this.annualInterestRate = annualInterestRate;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public double getBalance() {
            return balance;
        }
    
        public void setBalance(double balance) {
            this.balance = balance;
        }
    
        public double getAnnualInterestRate() {
            return annualInterestRate;
        }
    
        public void setAnnualInterestRate(double annualInterestRate) {
            this.annualInterestRate = annualInterestRate;
        }
    
    
    }
    
    
    
    class CustomerTestOne{
        private String firstName;
        private String lastName;
        private AccountTestOne account;
        public CustomerTestOne(String f, String l){
        }
    
        public String getFirstName() {
            return firstName;
        }
    
        public String getLastName() {
            return lastName;
        }
    
        public AccountTestOne getAccount() {
            return account;
        }
    
        public void setAccount(AccountTestOne account) {
            this.account = account;
        }
    }
    practice-one
     
    1.按照如下的 UML 类图,创建相应的类,提供必要的结构 
    
    
    
    
     
    在提款方法 withdraw()中,需要判断用户余额是否能够满足提款数额的要求,如果不能,
    应给出提示。deposit()方法表示存款。 
     
    2. 按照如下的 UML 类图,创建相应的类,提供必要的结构 
     
    
    
    
    3. 按照如下的 UML 类图,创建相应的类,提供必要的结构 
     
    
    
    
    
     
     
     
     addCustomer 方法必须依照参数(姓,名)构造一个新的 Customer 对象,然后把
    它放到 customer 数组中。还必须把 numberOfCustomer 属性的值加 1。 
     getNumOfCustomers 方法返回 numberofCustomers 属性值。 
    尚硅谷 Java 基础编程  宋红康 
     
     getCustomer 方法返回与给出的 index 参数相关的客户。 
    4. 创建 BankTest 类,进行测试。

    package关键字:

    package关键字的使用:

    1、为了更好的实现项目中类的管理,提供包的概念
    2、使用package声明类或者接口属性,声明再源文件首行
    
    
    同一个目录下不能命名相同的接口或者是类

    Practices

    1. 构造器的作用是什么?使用 中有哪些注意点(>=3条)
    1 :创建对象,
    2: 初始化对象结构
    
    使用: 在构造器中this只能调用其它的构造器不能调用当前构造器本身
            2: this(形参列表) 声明在构造器首行
            3: 一个构造器中只能有一个this去调用其它构造器

    2.关于类的属性的赋值,有几种赋值的方式。谈谈赋值的先后顺序

    默认初始化-显式初始化-构造器中初始化-对象.方法 或 对象.属性 给属性赋值

    3.this关键字可以用来调用哪些结构,简单说明一下其使用。

    this:属性、方法、构造器
    this:理解为当前对象,当前正在创建的对象

    4. Java中目前学习涉及到的四种权限修饰符都有什么?并说明各自的权限范围

    5. 创建Circle类,提供私有的radius属性,提供相应的get和set方法,提供求圆面积的方法。

    private double radius;
    public void setRadius(double radius){
        this.radius = radius;
    }
    public double getRadius(){
        return radius;
    }
    public double findArea(){
        return 3.14 * getRadius() * radius;
    }

    .

  • 相关阅读:
    dup/dup2函数
    read/write函数
    lseek函数
    流程控制
    vim普通模式
    vim实用技巧1
    python源代码解读
    python变量命名规则
    python之字符串2
    Docker系列文章
  • 原文地址:https://www.cnblogs.com/zhaoyunlong/p/10718802.html
Copyright © 2020-2023  润新知