面向对象的特征有哪些方面?

参考解答

1. 抽象

抽象是简化复杂现实问题的途径,是面向对象编程的基础。

数据抽象 提取客观事物中所关注的属性,放置在类定义中,称为数据抽象。 例如,我们的系统中有“用户”这一概念,这时,就需要将我们关注的属性如:用户账号,用户姓名,登录密码,联系方式等提取出来,抽象为User类。而那些无关的属性,如长相、政治面貌等,则要在抽象的过程中舍弃。

行为抽象 在数据抽象的基础上,需要将对象的行为逻辑抽取至类定义中,这称为行为抽象。例如,用户需要登录检查、需要根据用户属性进行过滤查询,这都属于用户的行为,它们将作为方法定义在类中。

2. 封装(encapsulation)

封装的思想是对数据进行“信息隐藏”,将数据设为私有,不允许直接访问,而是通过公共方法间接访问,这样的好处是可以对数据的读写加以控制。

例1:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

public class Main {

  public static void main(String[] args) {
    // 创建User对象,原始密码为123
    User user = new User("张三", "123");

    // 密码信息被隐藏了
    System.out.println(user.getPassword());
    // 输出202cb962ac59075b964b07152d234b70

    // 验证密码是否正确
    System.out.println(user.validate("456"));
    // 输出false
    System.out.println(user.validate("123"));
    // 输出true
  }

}

class User {
  private String username;
  private byte[] encryptPassword;

  public User(String username, String password) {
    this.username = username;
    // 密码加密存储
    this.encryptPassword = encrypt(password);
  }

  public String getUsername() {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  // 返回密码加密后的16进制格式
  public String getPassword(){
    StringBuilder sb = new StringBuilder(32);
    for (int i = 0; i < this.encryptPassword.length; i++) {    
      String hex = Integer.toHexString(this.encryptPassword[i] & 0xFF);    
      if (hex.length() == 1) {    
        sb.append("0");    
      }    
      sb.append(hex);
    }
    return sb.toString();
  }

  // 加密,这里的private也体现了一种加密这种行为的“信息隐藏”
  private byte[] encrypt(String password){
    try {
      MessageDigest md = MessageDigest.getInstance("md5");
      return md.digest(password.getBytes());
    } catch (NoSuchAlgorithmException e) {
      throw new RuntimeException(e);
    }
  }

  // 只能通过公共方法验证密码的正确性
  public boolean validate(String password) {
    return Arrays.equals(this.encryptPassword, encrypt(password));
  }

}

封装还可以对数据结构进行“信息隐藏”,让使用者无须关心其内部实现。比如对于LinkedList 类,我们都知道通过其 add(Object o) 可以向list中添加对象,remove(Object o) 可以移除list中的对象,但其内部怎么实现的对使用者隐藏起来了。

例2:

public class LinkedList<E> extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
  // 通过内部的Node类,来维护整个链表结构,但对于使用者,我们不需要关心它
  private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
      this.item = element;
      this.next = next;
      this.prev = prev;
    }
  }
  ...
}

3. 继承(inheritance)

继承的思想是避免数据及方法定义的重复、冗余。将通用的属性、方法定义放置在父类当中,在继承了这个父类的子类里就不必再次出现这些定义。

  • java中仅能单继承
  • java中的顶层父类是java.lang.Object
  • 构造方法不能被继承
  • private的属性和方法不能被继承
  • 可以通过方法重写来覆盖掉继承的方法
  • 不要滥用继承,只有在类与类是is-a关系时才考虑使用继承,如果是has-a关系时则要使用组合

4. 多态(polymorphism)

多态的思想是一个方法或一个类型,它们在使用时表现出不同的行为。

多态的好处是:

  • 让代码变得通用、易扩展
  • 用一个父类型来统一处理它的子类对象
  • 或用一个接口类型来统一处理它的实现对象
  • 面向父类型或接口编程,方便替换不同的子类或实现类
  • java中实现多态的关键在于向上转型+方法重写

例1: 看起来都是在调用一个名为t1的方法,但由于给它的参数类型不同,导致了运行时的行为不同。这在多态中称为Ad hoc polymorphism,发生在编译期间:

public static void t1(double a) {
  System.out.println("double...");
}

public static void t1(int a) {
  System.out.println("int ...");
}

public static void main(String[] args) {
  t1(10.0);
  t1(10);
}

例2: 通过泛型,达到了用一个方法来操作不同类型数组的目的。这在多态中称为Parametric polymorphism,也是发生在编译期间:

public static <T> void print(T[] array) {
  for (int i = 0; i < array.length; i++) {
    System.out.println(array[i]);
  }
}

public static void main(String[] args) {
  print(new Integer[] { 1, 2, 3 });
  print(new String[] { "a", "b", "c" });
}

例3: t方法中的 animal引用的类型为Animal,但根据它实际所引用的对象不同,运行时表现出的行为也不同。这在多态中称为Subtyping,发生在运行期间:

public class Test20 {

  public static void t(Animal animal) {
    animal.talk();
  }

  public static void main(String[] args) {
    t(new Cat()); // 输出 喵
    t(new Dog()); // 输出 汪
  }

}

abstract class Animal {
  abstract void talk();
}

class Cat extends Animal {
  @Override
  void talk() {
    System.out.println("喵");
  }
}

class Dog extends Animal {
  @Override
  void talk() {
    System.out.println("汪");
  }
}

results matching ""

    No results matching ""