2008-08-21 41 views
5

Tôi có một bộ sưu tập các lớp kế thừa từ một lớp trừu tượng mà tôi đã tạo. Tôi muốn sử dụng lớp trừu tượng như một nhà máy để tạo ra các cá thể triển khai thực hiện cụ thể của lớp trừu tượng của tôi.Có cách nào để tạo một hàm khởi tạo chỉ hiển thị với một lớp cha trong C#?

Có cách nào để ẩn một hàm tạo từ tất cả mã ngoại trừ một lớp cha.

Tôi muốn làm điều này về cơ bản

public abstract class AbstractClass 
{ 
    public static AbstractClass MakeAbstractClass(string args) 
    { 
     if (args == "a") 
      return new ConcreteClassA(); 
     if (args == "b") 
      return new ConcreteClassB(); 
    } 
} 

public class ConcreteClassA : AbstractClass 
{ 
} 

public class ConcreteClassB : AbstractClass 
{ 
} 

Nhưng tôi muốn ngăn chặn bất cứ ai từ trực tiếp instantiating 2 lớp bê tông. Tôi muốn đảm bảo rằng chỉ có phương thức MakeAbstractClass() mới có thể khởi tạo các lớp cơ sở. Có cách nào để làm điều này không?

CẬP NHẬT
Tôi không cần phải truy cập vào bất kỳ phương pháp cụ thể của ConcreteClassA hoặc B từ bên ngoài của lớp trừu tượng. Tôi chỉ cần các phương thức công khai mà lớp Abstract của tôi cung cấp. Tôi không thực sự cần phải ngăn các lớp Concrete được khởi tạo, tôi chỉ cố gắng tránh nó vì chúng không cung cấp các giao diện công cộng mới, chỉ các triển khai khác nhau của một số thứ rất cụ thể bên trong lớp trừu tượng.

Với tôi, giải pháp đơn giản nhất là make child classes as samjudson mentioned. Tôi muốn tránh điều này tuy nhiên vì nó sẽ làm cho tập tin lớp trừu tượng của tôi 'lớn hơn rất nhiều so với tôi muốn nó được. Tôi muốn giữ các lớp học tách ra trên một vài tập tin cho tổ chức.

Tôi đoán không có giải pháp dễ dàng nào cho việc này ...

Trả lời

2

Bạn có thể làm cho phụ lớp lớp con, một cái gì đó như thế này:

public abstract class AbstractClass 
{ 
    public static AbstractClass MakeAbstractClass(string args) 
    { 
     if (args == "a") 
      return new ConcreteClassA(); 
     if (args == "b") 
      return new ConcreteClassB(); 
    } 

    private class ConcreteClassA : AbstractClass 
    { 
    } 

    private class ConcreteClassB : AbstractClass 
    { 
    } 
} 

@Vaibhav này không thực sự có nghĩa là các lớp học cũng được ẩn. Nhưng điều này là như xa như tôi biết cách duy nhất để hoàn toàn ẩn các nhà xây dựng.

Chỉnh sửa: Như những người khác đã đề cập đến cùng một điều có thể được thực hiện bằng cách sử dụng Reflection, mà thực sự có thể gần với những gì bạn muốn trở thành trường hợp - ví dụ phương pháp trên trả lời các lớp cụ thể nằm trong cùng một tệp lớp Tóm tắt, có lẽ không thuận tiện lắm. Có nói rằng cách này là một 'Hack' tốt đẹp, và tốt nếu số lượng và độ phức tạp của các lớp cụ thể là thấp.

+0

Ví dụ hay, nhưng hãy đặt tên một chút .NETy và gọi nó là "CreateAbstractClass (string args)" vì lợi ích mã hóa tiêu chuẩn :) –

1

Không, tôi không nghĩ chúng tôi có thể làm điều đó.

3

Nếu các lớp học trong cùng một hội đồng, bạn có thể không làm cho các nhà xây dựng nội bộ?

0

Bạn có thực sự cần để thực hiện việc này không? Nếu bạn đang sử dụng một số loại mẫu giả nhà máy mà không cần thiết kế thực sự cho nó, bạn sẽ chỉ làm cho mã của bạn khó hiểu hơn, duy trì và mở rộng.

Nếu bạn không cần thực hiện việc này, chỉ cần triển khai đúng mẫu nhà máy. Hoặc, nhiều hơn ALTy, sử dụng một khuôn khổ DI/IoC.

6

Với tôi, giải pháp đơn giản nhất là làm cho các lớp con là samjudson được đề cập. Tôi muốn tránh điều này tuy nhiên vì nó sẽ làm cho tệp của tôi là lớp trừu tượng 'lớn hơn rất nhiều so với Tôi muốn nó trở thành.Tôi muốn giữ các lớp tách ra trên một vài tệp cho tổ chức .

Không sao cả, chỉ cần sử dụng một phần từ khóa và bạn có thể chia lớp bên trong thành nhiều tệp tùy ý. Bạn không cần phải giữ nó trong cùng một tập tin.

câu trả lời trước:

Có thể nhưng chỉ với sự phản ánh

public abstract class AbstractClass 
{ 
    public static AbstractClass MakeAbstractClass(string args) 
    { 
     if (args == "a") 
      return (AbstractClass)Activator.CreateInstance(typeof(ConcreteClassA), true); 
     if (args == "b") 
      return (AbstractClass)Activator.CreateInstance(typeof(ConcreteClassB), true); 
    } 
} 

public class ConcreteClassA : AbstractClass 
{ 
    private ConcreteClassA() 
    { 
    } 
} 

public class ConcreteClassB : AbstractClass 
{ 
    private ConcreteClassB() 
    { 
    } 
} 

và đây là mô hình khác, mà không xấu xí MakeAbstractClass (string args)

public abstract class AbstractClass<T> where T : AbstractClass<T> 
{ 
    public static T MakeAbstractClass() 
    { 
     T value = (T)Activator.CreateInstance(typeof(T), true); 
     // your processing logic 
     return value; 
    } 
} 

public class ConcreteClassA : AbstractClass<ConcreteClassA> 
{ 
    private ConcreteClassA() 
    { 
    } 
} 

public class ConcreteClassB : AbstractClass<ConcreteClassB> 
{ 
    private ConcreteClassB() 
    { 
    } 
} 
-2

gì bạn cần làm là ngăn chặn hàm tạo mặc định được tạo. Nội bộ có thể được thay đổi thành công khai nếu các lớp không nằm trong cùng một assembly.

public abstract class AbstractClass{ 

public static AbstractClass MakeAbstractClass(string args) 
{ 
    if (args == "a") 
     return ConcreteClassA().GetConcreteClassA(); 
    if (args == "b") 
     return ConcreteClassB().GetConcreteClassB(); 
} 
} 

public class ConcreteClassA : AbstractClass 
{ 
    private ConcreteClassA(){} 

    internal static ConcreteClassA GetConcreteClassA(){ 
     return ConcreteClassA(); 
    } 
} 

public class ConcreteClassB : AbstractClass 
{ 
    private ConcreteClassB(){} 
    internal static ConcreteClassB Get ConcreteClassB(){ 
     return ConcreteClassB(); 
    } 

} 
0

Bạn không thể sử dụng từ khóa partial để tách mã cho một lớp thành nhiều tệp?

0

Nếu bạn đang sử dụng lớp này trong một cụm dịch vụ riêng biệt, bạn có thể sử dụng từ khóa nội bộ.

public class AbstractClass 
{ 
    public AbstractClass ClassFactory(string args) 
    { 
     switch (args) 
     { 
      case "A": 
       return new ConcreteClassA();    
      case "B": 
       return new ConcreteClassB();    
      default: 
       return null; 
     } 
    } 
} 

public class ConcreteClassA : AbstractClass 
{ 
    internal ConcreteClassA(){ } 
} 

public class ConcreteClassB : AbstractClass 
{ 
    internal ConcreteClassB() {} 
} 
1

Tiếp theo từ accepted answer, nếu bạn đã có một giao diện công cộng và thực hiện các lớp tin thực hiện giao diện, bạn có thể sau đó trả về một con trỏ đến giao diện và bất kỳ ai ngoài cha mẹ của bạn lớp trừu tượng sau đó có thể sử dụng chúng (trong khi vẫn ẩn các lớp trẻ em).

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