Почему частные методы в java не переопределяются из metaClass в Groovy? [Дубликат]

Динамический SQL PIVOT

Разный подход для создания столбцов string

create table #temp
(
    date datetime,
    category varchar(3),
    amount money
)

insert into #temp values ('1/1/2012', 'ABC', 1000.00)
insert into #temp values ('2/1/2012', 'DEF', 500.00)
insert into #temp values ('2/1/2012', 'GHI', 800.00)
insert into #temp values ('2/10/2012', 'DEF', 700.00)
insert into #temp values ('3/1/2012', 'ABC', 1100.00)

DECLARE @cols  AS NVARCHAR(MAX)='';
DECLARE @query AS NVARCHAR(MAX)='';

SELECT @cols = @cols + QUOTENAME(category) + ',' FROM (select distinct category from #temp ) as tmp
select @cols = substring(@cols, 0, len(@cols)) --trim "," at end

set @query = 
'SELECT * from 
(
    select date, amount, category from #temp
) src
pivot 
(
    max(amount) for category in (' + @cols + ')
) piv'

execute(@query)
drop table #temp

Результат

date                    ABC     DEF     GHI
2012-01-01 00:00:00.000 1000.00 NULL    NULL
2012-02-01 00:00:00.000 NULL    500.00  800.00
2012-02-10 00:00:00.000 NULL    700.00  NULL
2012-03-01 00:00:00.000 1100.00 NULL    NULL
2
задан Jay Shark 27 March 2014 в 20:24
поделиться

4 ответа

Кажется, вы не можете использовать метапрограммирование Groovy, чтобы заменить методы классов Java - даже публичные методы - попробуйте выполнить следующие действия в консоли Groovy:

ArrayList.metaClass.remove = { obj ->
  throw new Exception('remove')
}

ArrayList.metaClass.remove2 = { obj ->
  throw new Exception('remove2')
}

def a = new ArrayList()
a.add('it')

// returns true because the remove method defined by ArrayList is called, 
// i.e. our attempt at replacing it above has no effect
assert a.remove('it')

// throws an Exception because ArrayList does not define a method named remove2, 
// so the method we add above via the metaClass is invoked
a.remove2('it')

Если вы можете изменить исходный код из MyClass я либо сделал бы doSomethingCrazyExpensive защищенным, либо, желательно, реорганизовал его так, чтобы он был более дружественным к тестированию

public class MyClass {

    private ClassOfSomeSort property1;
    private ClassOfSomeOtherSort property2;
    private CrazyExpensive crazyExpensive;

    public MyClass(CrazyExpensive crazyExpensive) {
        this.crazyExpensive = crazyExpensive;
    }

    public void init(){

        property1 = new ClassOfSomeSort();
        property2 = new ClassOfSomeOtherSort();

        crazyExpensive.doSomethingCrazyExpensive();
    }
}

public interface CrazyExpensive {
    public void doSomethingCrazyExpensive();  
}

После внесения изменений выше, при тестировании MyClass вы можете легко создать экземпляр с помощью макета / заглушки CrazyExpensive.

0
ответ дан Dónal 25 August 2018 в 18:21
поделиться
1
ответ дан Renato 25 August 2018 в 18:21
поделиться
0
ответ дан Steve s. 25 August 2018 в 18:21
поделиться
2
ответ дан Will 25 August 2018 в 18:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: