【问题标题】:Limiting method access in protected section to few classes将受保护部分中的方法访问限制为少数类
【发布时间】:2010-06-07 15:35:04
【问题描述】:

我想将受保护方法的访问权限限制为仅对某些继承的类。

例如有一个像这样的基类

TBase = Class
  Protected
    Method1;
    Method2;
    Method3;
    Method4;
End;

我有两个从 TBase 派生的类

TDerived1 = Class(TBase)
  //Here i must access only Method1,Method2 and Method3
End;

TDerived2 = Class(TBase)
  //Here i must access only Method3 and Method4
End;

那么有没有可能 当我使用 TDerived1Method3 和 Method4 当我使用 TDerived2

的对象时

【问题讨论】:

    标签: delphi oop


    【解决方案1】:

    没有办法做到这一点。如果一个方法是protected,那么所有的后代类都可以访问它。如果您有两组可以轻松划分的独立功能,您可能需要重新考虑您的类设计。

    【讨论】:

      【解决方案2】:

      我会拆分它们,类似于Jeroen's answer

        TBase = class
        end;
      
        TBase12 = class(TBase)
        protected
          procedure Method1;
          procedure Method2;
        end;
      
        TBase34 = class(TBase)
        protected
          procedure Method3;
          procedure Method4;
        end;
      
        TDerived1 = class(TBase12)
        end;
      
        TDerived2 = class(TBase34)
        end;
      

      根据您的描述,这似乎比“单片”基类(如Mason already wrote)更好地模拟您的需求。

      【讨论】:

      • +1。这正是我重新思考班级设计的意思。
      • 只有在 Method1 和 Method2 不依赖 Method3 和 Method4(反之亦然)的情况下才可以进行这种重新设计;因此我没有重新设计它:-)
      • 是的,当然。确切的可能性取决于确切的情况。 :-)
      【解决方案3】:

      另一种方法 - 您可以使用接口来做到这一点...

      IBase1 = interface
        // press Ctrl+Shift+G here to generate your own sexy GUID
        procedure Method1;
        procedure Method2;
      end;
      
      IBase2 = interface
        // press Ctrl+Shift+G here again
        procedure Method3;
        procedure Method4;
      end;
      
      TBase = class(TInterfacedObject, IBase1, IBase2)
      public
        { IBase1 }
        procedure Method1;
        procedure Method2;
        { IBase2 }
        procedure Method3;
        procedure Method4;
      end;
      
      var
        B1: IBase1;
        B2: IBase2;
      begin
        B1 := TBase.Create as IBase1;
        B2 := TBase.Create as IBase2;
      
        B1.Method1; // works
        B1.Method3; // Can't compile
      
        B2.Method3; // works
      end;
      

      【讨论】:

        【解决方案4】:

        在我看来你的方法没有在正确的地方声明。

        如果 Method1 和 Method2 没有在 TBase 中调用,并且只能从 TDerived1 和后代中调用...那么这些方法应该在 TDerived1 中声明。

        如果 Method1/2 访问 TBase 的私有字段,那么您应该对 TBase 中的这些字段具有属性或 Getter/setter。

        但除非你给出更具体的理由说明为什么需要在 TBase 中声明这些方法,否则我会说在那里声明它们只是糟糕的设计。

        【讨论】:

          【解决方案5】:

          以类似方式发布适用于方法的私有/受保护/公共属性的解决方案。
          所以你可以这样做:

          unit PropertyAndMethodVisibilityPromotionUnit;
          
          interface
          
          type
            TBase = class
            private
              procedure Method1;
              procedure Method2;
              procedure Method3;
              procedure Method4;
            end;
          
            TBase1 = class(TBase)
            protected
              procedure Method1;
              procedure Method2;
            end;
          
            TBase2 = class(TBase)
            protected
              procedure Method3;
              procedure Method4;
            end;
          
            TDerived1 = class(TBase1)
              //Here i must access only Method1 and Method2
            end;
          
            TDerived2 = class(TBase2)
              //Here i must access only Method3 and Method4
            end;
          
          implementation
          
          procedure TBase.Method1;
          begin
          
          end;
          
          procedure TBase.Method2;
          begin
          
          end;
          
          procedure TBase.Method3;
          begin
          
          end;
          
          procedure TBase.Method4;
          begin
          
          end;
          
          procedure TBase1.Method1;
          begin
            inherited;
          end;
          
          procedure TBase1.Method2;
          begin
            inherited;
          end;
          
          procedure TBase2.Method3;
          begin
            inherited;
          end;
          
          procedure TBase2.Method4;
          begin
            inherited;
          end;
          
          end.
          

          注意事项:

          1. TBaseTBase1TBase2 位于同一单元中时有效。
          2. 这是一个针对潜在弱类设计的 hack,因此请务必检查您的类设计

          --杰罗恩

          【讨论】:

          • 你是否建议仅仅在类声明中“重新声明”一个方法来提高它的可见性?这对我在 D2007 中不起作用 - 我必须实现一个转发方法并且该方法必须在基类中受到保护。
          • 那种工作...如果类在同一个单元中声明,您可以使用该方法。只需让 TBase1.Method1 调用“继承的 Method1”。但这样做是毫无意义的。恕我直言,设计仍然很糟糕。
          • @Ulrich:我用一个更详细的例子编辑了这篇文章。 @Ken:完全同意,因此我在编辑中添加了注释。
          【解决方案6】:

          好的...这是实现您正在寻找的可能的方法。我认为它需要 Delphi 2005 或更高版本。 (或任何引入“Strict Protected|private”可见性的版本)

          TBase = Class
            Strict Protected
              procedure Method1;
              procedure Method2;
              procedure Method3;
              procedure Method4;
          End;
          
          TDerived1 = Class(TBase)
            Protected
              procedure Method1;
              procedure Method2;
              procedure Method3;   
          End;
          
          TDerived2 = Class(TBase)
            Protected
              procedure Method3;
              procedure Method4;
          End;
          
          TUserClass = class
            FImplementer : TDerived1;
          end;
          

          方法看起来像这样

          procedure TDerived2.Method3;
          begin
            inherited Method3;
          end;
          

          但是您的要求让我怀疑您的方法是否真的属于您的 TBase 类。似乎它们应该是静态过程,或者可能是另一个类的类过程。我不认为他们真的属于 TBase。

          【讨论】:

            猜你喜欢
            • 2012-06-02
            • 2020-07-26
            • 2013-04-06
            • 1970-01-01
            • 2020-05-02
            • 2017-12-14
            • 2014-05-01
            • 1970-01-01
            • 2012-11-25
            相关资源
            最近更新 更多