2017-01-09 11 views
7

Tôi có một nhiệm vụ cần được thực hiện nhưng tôi thực sự bị kẹt.Tạo đối tượng Theo một tệp đầu vào

Về cơ bản, tôi đã một số quan hệ thừa kế như thế này:

Animal

Pet WildAnimal

Bird Dog Cat Fish || rắn Eagle

Animal là phụ huynh của thú nuôi và hoang dã Thú vật. Thú cưng là cha mẹ của Chim, Mèo, Chó, Cá. WildAnimal là cha mẹ của Snake và Eagle.

Tác vụ muốn tôi đọc đầu vào từ tệp là "input.txt" và tạo đối tượng Động vật.

"INPUT.TXT" giống như:

kiwi Bird charlie Eagle xoài cá tiêu Dog góc Cát tweety Bird bob Chó Ziggy rắn

tôi có thể nhận được tất cả những cái tên nhưng tôi không thể tìm ra cách để hiểu loại đối tượng nào mà mỗi cái tên đại diện.

Đây là phương pháp chính:

public static void main(String[] args) throws IOException { 
    String s =""; 
    int nameCounter = 0; 
    Animal[] animals = new Animal[100]; 

    try{ 
    Scanner input = new Scanner(Paths.get("input.txt")); 

     while (input.hasNext()) { 
      s = input.next(); 
      Animal animal = new Animal(s); 
      animals[nameCounter] = animal; 
      nameCounter += 2; 
     } 
    }catch(Exception e){ 
     e.printStackTrace(); 
    } 
} 

Đây là lớp động vật:

public class Animal { 
private String name; 
private int numberOfLegs; 
private int numberOfWings; 

public Animal(String name){ 
    this.name = name; 
    numberOfLegs = 4; 
    numberOfWings = 0; 
} 

public String getName() { 
    return name; 
} 
public void setName(String name) { 
    this.name = name; 
} 
public int getNumberOfLegs() { 
    return numberOfLegs; 
} 
public void setNumberOfLegs(int numberOfLegs) { 
    this.numberOfLegs = numberOfLegs; 
} 
public int getNumberOfWings() { 
    return numberOfWings; 
} 
public void setNumberOfWings(int numberOfWings) { 
    this.numberOfWings = numberOfWings; 
} 
public void talk(){ 
    System.out.printf("<Silence>"); 
} 
public void fly(){ 
    System.out.printf("%s cannot fly", getName()); 
} 
public void run(){ 
    System.out.printf("%s is running", getName()); 
} 

}

tôi có thể thêm tất cả các lớp khác nếu bạn muốn nhưng tôi không nghĩ rằng bạn sẽ cần chúng.

+0

[This] (http://stackoverflow.com/questions/1268817/create-new-class-from-a-variable-in-java) có thể giúp bạn. – Blobonat

+0

Cảm ơn bạn đã chấp nhận nhanh chóng! – GhostCat

Trả lời

4

Bạn phải tạo nhanh đối tượng của lớp cụ thể của mình; dựa trên chuỗi đến.

Ví dụ: nếu tên lớp từ tệp là Bird ... thì bạn phải gọi new Bird() bằng cách nào đó.

Có hai cách để đạt được điều đó:

  1. Sử dụng phản xạ (bạn thực sự có thể nhanh chóng lớp học "bởi chuỗi"; mà không biết bất cứ điều gì về lớp đó)
  2. Bằng cách sử dụng một câu lệnh switch

Reflection là chủ đề "nâng cao" (và rất dễ sử dụng sai); vì vậy tôi thực sự khuyên bạn nên đi cho phương án 2, như:

private Animal createAnimalFor(String className, String animalName) { 
    switch (className) { 
    case "Bird": return new Bird(animalName); 
    ... 
    default: throw new IllegalArgumentException("Dont know how to create object for unknown class: " + className); 
    } 
} 

(đoạn mã trên có nghĩa là "FYI" - Tôi không chạy nó thông qua trình biên dịch, nó có nghĩa là để cung cấp cho bạn một ý tưởng về cách thực hiện điều này).

Một số lưu ý ngoài rằng:

  • Xem xét sử dụng một thức lĩnh vực cho những thuộc tính của đối tượng của bạn mà không thể thay đổi. Bạn không cần setter cho tên đó; chỉ cần đặt tên là tham số cho hàm tạo. Nói cách khác: chỉ làm cho những trường đó "có thể thay đổi" có ý nghĩa để thay đổi. Mọi thứ khác tốt hơn nên là final.
  • Thay vì sử dụng một mảng với 100 vùng trống, bạn có thể sử dụng java.util.ArrayList và chỉ thêm nhiều động vật mới như bạn tìm thấy trong tệp đó.
  • Cân nhắc thêm phương thức equals/hashCode vào lớp Động vật của bạn (không bắt buộc, nhưng bạn nên đọc lý do tại sao có ý nghĩa rất thường xuyên).
  • Có lẽ quan trọng nhất: xem xét không phải đặt tất cả các phương thức khác nhau đó trực tiếp vào lớp cơ sở của bạn. Nó có thể làm cho tinh thần hơn để tạo ra một trong hai lớp con trừu tượng mà thêm một số chức năng, hoặc sử dụng giao diện, như interface FlyingAnymal { void fly() }; mà lớp con cụ thể của bạn sau đó sẽ thực hiện. Nó không phải là thực sự tốt thực hành để đặt rất nhiều phương pháp trên lớp cơ sở của bạn ... mà chỉ đơn giản là không có ý nghĩa cho tất cả của các lớp phụ.
+0

Tôi nghe nói về sự phản chiếu nhưng tôi không thể có được ý tưởng. Mặt khác, chuyển đổi chắc chắn là một cái gì đó tôi có thể làm cho bây giờ. Cảm ơn rất nhiều. –

+1

Fyi: Tôi đã thêm một số ghi chú/gợi ý chung cho dự án của bạn. Tôi hy vọng nó sẽ giúp ;-) – GhostCat

3

Nếu bạn thực sự muốn sử dụng phản ánh để làm như vậy (mà tôi cũng sẽ không khuyến khích), đây là mẫu mã:

String name = input.next(); 
String className = input.next(); 
// apply transformations to className as needed 
Class<Animal> c = (Class<Animal>) Class.forName(className); 
Constructor<Animal> constr = c.getDeclaredConstructor(String.class); // retrieves the Animal(String name) constructor 
Animal a = constr.newInstance(name); 

Tôi không nghĩ rằng mã là rất phức tạp, nhưng rất ít người có đã từng sử dụng sự phản chiếu để chúng có vấn đề duy trì nó, và nó được kết hợp chặt chẽ với các định nghĩa lớp học của bạn để nó có lẽ sẽ phải được duy trì rất nhiều.

+0

Vâng, điều đó có vẻ hợp lý. Tôi chắc chắn sẽ thử điều này quá. –

Các vấn đề liên quan