2009-11-18 2 views
1

Допустим, у меня есть следующий класс, который я не позволил изменить:Вызов метода экземпляра без вызова конструктора

public class C 
{ 
    public C() { CreateSideEffects(); } 
    public void M() { DoSomethingUseful(); } 
} 

, и я должен позвонить M без вызова конструктора. Является ли это возможным?

+6

Этот вопрос является эквивалентом спрашивать «Я хочу назвать свою кошку, не имея кошку Как мне это сделать?» –

+0

@programminghero +1 для lolz. Дайте ему преимущество в сомнении. Возможно, это класс сторонних разработчиков, что он действительно хочет функциональности 'C.M()', и он не контролирует его. :) –

+1

Что-то для рассмотрения: если метод изменяет состояние экземпляра, это метод * stateful * и должен быть методом экземпляра. если метод ** не ** изменяет состояние экземпляра, это * безъядерный * метод и должен быть статическим методом. ergo, метод экземпляра является одной из двух вещей: либо 1) метод stateful, но и требует правильно созданного экземпляра, или 2) очень плохо написанный класс. –

ответ

7

Нет. Поскольку метод C.M() является методом экземпляра, вам необходимо создать экземпляр, что означает вызов конструктора.

Является C классом, которым владеет ваша команда? Если она есть, но вы по приказу, чтобы оставить его в покое, вы могли бы сделать так, чтобы лоббировать либо:

  1. Эти побочные эффекты должны быть переработан и удалены
  2. Функциональность C.M() метод переехал в другой класс или статический.

Если C от 3-й стороной, вы будете иметь проблемы, и, возможно, придется повторить функциональность C.M() в методе вы сделать собственный.

+0

+1 для перемещения «побочных эффектов». конструктор должен ** никогда не выполнять какую-либо работу, кроме назначения члена. тяжелый подъем всегда должен быть делегирован методу post-ctor, чтобы избежать исключений при создании экземпляров. –

+0

@johnnyg Ну, не обязательно всегда. Если ваши объекты загружаются через IoC, вы не сможете их инициализировать, потому что интерфейс может не иметь метода 'Initialise()', и вы не можете гарантировать, что он будет вызван, даже если бы это произошло. Если классы выполняют ленивую инициализацию при вызове методов и т. Д., Это помогает, но на самом деле не так уж плохо делать некоторую работу в ctor. Проблема в том, что то, что он делает, вызывает реальные надлежащие побочные эффекты и, следовательно, вызывает проблемы в других местах. –

1

Чтобы вызвать метод экземпляра, вам понадобится экземпляр! И - по уважительным причинам - единственный способ получить один - через конструктор. В противном случае весь объект может находиться в неопределенном или бесполезном состоянии, поскольку инициализация не была выполнена. Так что даже если бы был какой-то хак, это было бы неплохо!

Единственный вид члена класса, который вы можете вызвать без экземпляра, - это статические методы.

4

Да, вы можете!

Излишне говорить, что это плохой дизайн, но вы уже знаете это и не можете его изменить. Если нужно, вы можете попытаться частично издеваться над классом.

EDIT: Только что понял, что в моем примере используется Java не C#. Однако @Guillaume предлагает образец кода для C#. По-видимому, он даже встроен в API runtime!

В Java, С Mockito, это делает работу:

C c = Mockito.mock(C); 
Mockito.doCallRealMethod().when(c).M(); 
// If M() isn't a void method 
// when(c.M()).thenCallRealMethod(); 
c.M(); 

Однако, в этом случае M() может не зависеть от какого-либо государства, заданный в конструкторе.

Для получения дополнительной информации о частичном издевательстве см. Это FAQ Question. Однако издевательство в основном используется для тестирования.

+1

Будь то, что пересекает потоки совсем немного, иначе ты получишь +1 только за то, что ты такой злой гений. :) –

+0

@Neil, вопрос в том, возможно ли это или нет. Вопреки сказанному, это возможно. Это другой вопрос о том, хорошо это или нет. – notnoop

+0

Да, я знаю, но это тонкая черта о том, возможно ли что-то по сравнению с тем, нужно ли это делать. Если кто-то спросил, можно ли выдержать падение с окна на 2-м этаже, вы можете сказать «да», но вы по-прежнему рекомендуете, чтобы они этого не делали. Вы можете считать белую ложь и сказать им нет. :) Я понятия не имел, что это возможно, и сказал так же в моем ответе. Для всех целей и целей ** ** невозможно. –

1

Я не скажу вам, что это плохая идея, поскольку кажется, что вам сказали, что этого достаточно. Ой, извините, я предполагаю, что я только что сделал ... все равно вот как это сделать:

using System.Runtime.Serialization; 

    C myInstance = FormatterServices.GetUninitializedObject(typeof(C)); 
    myInstance.M(); 

Метод «» GetUninitializedObject выше возвращает экземпляр объекта без вызова любого экземпляра CTOR (очевидно любого статического типа CTOR воли все еще выполняется).Затем вы можете вызывать поля экземпляра, если это необходимо, или просто вызывать методы.

Опять же, плохая идея в целом;)